This is the full developer documentation for tree-sitter-language-pack # tree-sitter-language-pack > Parse and understand source code in 371 languages, from the language you already work in. Install once, call one API, and get back syntax trees, functions, imports, symbols, and LLM-ready chunks — no grammars to compile, no toolchain to wire up. ## Why tree-sitter-language-pack [Section titled “Why tree-sitter-language-pack”](#why-tree-sitter-language-pack) Parse any language without wiring up grammars One install covers 371 languages — Python, Rust, Go, Java, TypeScript, C++, Kotlin, Swift, Zig, Elixir, Haskell, Julia, R, and hundreds more. Nothing to compile, nothing to fetch by hand. Fast enough for real-time tooling Parsing keeps up with editor keystrokes and large-repo scans, so you can build linters, formatters, and analysis that respond instantly. Only download the parsers you use The base install stays small. Each parser is fetched and cached the first time you touch its language, so you never ship 371 grammars you don’t need. Find functions, classes, and imports in one call Go past raw syntax trees: pull functions, classes, imports, exports, symbols, comments, and docstrings out of any file with a single call. Chunk code your LLM can actually use Split source at real boundaries — functions, classes, blocks — so each chunk stays whole for embeddings and prompt windows instead of cutting mid-statement. Use your language's own parser types In Python, Node.js, Go, Java, C#, Kotlin, Swift, Zig, and C, `get_language()` hands back your ecosystem’s native `Language` object, ready to pass to your existing parser. ## Language support [Section titled “Language support”](#language-support) | Language | Install | Docs | | ------------------------ | ------------------------------------------------------------------ | ----------------------------------------------- | | **Python** | `pip install tree-sitter-language-pack` | [API Reference](/reference/api-python/) | | **TypeScript / Node.js** | `npm install @xberg-io/tree-sitter-language-pack` | [API Reference](/reference/api-typescript/) | | **Rust** | `cargo add tree-sitter-language-pack` | [API Reference](/reference/api-rust/) | | **Go** | `go get github.com/xberg-io/tree-sitter-language-pack/packages/go` | [API Reference](/reference/api-go/) | | **Java** | Maven Central `io.xberg.treesitterlanguagepack` | [API Reference](/reference/api-java/) | | **Kotlin (Android)** | Maven `io.xberg.tslp.android:tree-sitter-language-pack-android` | [API Reference](/reference/api-kotlin-android/) | | **C#** | `dotnet add package XbergIo.TreeSitterLanguagePack` | [API Reference](/reference/api-csharp/) | | **Ruby** | `gem install tree_sitter_language_pack` | [API Reference](/reference/api-ruby/) | | **PHP** | `composer require xberg-io/tree-sitter-language-pack` | [API Reference](/reference/api-php/) | | **Elixir** | `{:tree_sitter_language_pack, "~> 1.14"}` | [API Reference](/reference/api-elixir/) | | **Dart / Flutter** | `dart pub add tree_sitter_language_pack` | [API Reference](/reference/api-dart/) | | **Swift** | Swift Package Manager | [API Reference](/reference/api-swift/) | | **Zig** | `zig fetch --save` from GitHub | [API Reference](/reference/api-zig/) | | **WebAssembly** | `npm install @xberg-io/tree-sitter-language-pack-wasm` | [API Reference](/reference/api-wasm/) | | **C (FFI)** | Shared library + header | [API Reference](/reference/api-c/) | | **CLI** | `brew install xberg-io/tap/ts-pack` | [CLI Guide](/guides/cli/) | [See all 371 supported languages →](/languages/) ## Quick example [Section titled “Quick example”](#quick-example) * Python Intel: process with all features enabled Python ```python from tree_sitter_language_pack import process def main() -> None: source = "# A comment\ndef greet(name):\n \"\"\"Say hello.\"\"\"\n return f'Hi {name}'\n\nimport os\n" config = {"language": "python"} result = process(source, config) print(result.language) print(result.structure) print(result.structure[0].kind) print(result.imports) print(result.metrics.total_lines) print(result.metrics.error_count) main() ``` * Node.js Intel: process with all features enabled TypeScript ```typescript import { ProcessConfig, process } from "@xberg-io/tree-sitter-language-pack"; function main() { const config: ProcessConfig = { language: "python" }; const result = process("# A comment\ndef greet(name):\n \"\"\"Say hello.\"\"\"\n return f'Hi {name}'\n\nimport os\n", config); console.log(result.language); console.log(result.structure); console.log(result.structure?.[0]?.kind); console.log(result.imports); console.log(result.metrics?.totalLines); console.log(result.metrics?.errorCount); } void main(); ``` * Rust Parse a Python function definition and assert node type Rust ```rust use tree_sitter_language_pack::process; fn main() { let source = r#"def hello(): pass"#; let config_json: serde_json::Value = serde_json::from_str(r#"{"language":"python"}"#).unwrap(); let config = serde_json::from_value(config_json).unwrap(); let result = process(source, &config); println!("{:?}", result); } ``` ## Part of Xberg.io [Section titled “Part of Xberg.io”](#part-of-xbergio) [Xberg](https://github.com/xberg-io/xberg)Document intelligence: text, tables, metadata from 101 formats with optional OCR. [Xberg Enterprise](https://github.com/xberg-io/xberg-enterprise)Managed extraction API with SDKs, dashboards, and observability. [crawlberg](https://github.com/xberg-io/crawlberg)Web crawling and scraping with HTML→Markdown and headless-Chrome fallback. [html-to-markdown](https://github.com/xberg-io/html-to-markdown)Fast, lossless HTML→Markdown engine. [liter-llm](https://github.com/xberg-io/liter-llm)Universal LLM API client with native bindings for 14 languages and 165 providers. [tree-sitter-language-pack](https://github.com/xberg-io/tree-sitter-language-pack)Tree-sitter grammars and code-intelligence primitives. [alef](https://github.com/xberg-io/alef)The polyglot binding generator that produces every per-language binding across the 5 polyglot repos. ## Explore the docs [Section titled “Explore the docs”](#explore-the-docs) [Get Started](/getting-started/quickstart/)Install for your language, download parsers, and parse your first file in minutes. [Parsing](/guides/parsing/)Build syntax trees, choose a language, walk nodes, and handle parse errors. [Code Intelligence](/guides/intelligence/)Structure, imports, exports, symbols, comments, and docstrings — not just raw nodes. [Chunking for LLMs](/guides/chunking/)Split source at natural boundaries so chunks stay semantically intact. [Concepts](/concepts/architecture/)Architecture, download model, ABI compatibility, and language passthrough interop. [API Reference](/reference/api-python/)Complete reference for every binding across 15 language surfaces. ## Getting help [Section titled “Getting help”](#getting-help) * **Bugs & feature requests** — [Open an issue on GitHub](https://github.com/xberg-io/tree-sitter-language-pack/issues) * **Community chat** — [Join the Discord](https://discord.gg/xt9WY3GnKR) * **Contributing** — [Read the contributor guide](/contributing/) # Changelog > Release history and notable changes for tree-sitter-language-pack. All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ## Unreleased [Section titled “Unreleased”](#unreleased) ## 1.14.1 - 2026-08-04 [Section titled “1.14.1 - 2026-08-04”](#1141---2026-08-04) ### Fixed [Section titled “Fixed”](#fixed) * Ruby binding no longer exports generated types into the global `Object` namespace (issue #173, the `Parser` collision with the `parser` gem); generated types stay namespaced under `TreeSitterLanguagePack`. ### Changed [Section titled “Changed”](#changed) * Vendored grammar scanners now classify characters through a deterministic utf8proc-backed wide-ctype shim instead of libc ``, making parse trees (and downstream formatting) identical across macOS and glibc. Pinned `tree-sitter-cli` to `0.26.11` in CI. ## 1.14.0 - 2026-08-01 [Section titled “1.14.0 - 2026-08-01”](#1140---2026-08-01) ### Added [Section titled “Added”](#added) * Add 65 tree-sitter grammars, raising coverage from 306 to 371. New languages include Slint, MoonBit, Aiken, Koka, Koto, Unison, Leo, Motoko, Eiffel, Picat, Cython, Ballerina, SAS, D2, Vala, and Fluent, alongside DSL/schema/query grammars (YANG, FlatBuffers, Avro, Cypher, SpiceDB, Kusto, PostgreSQL, T-SQL, WDL, SysML, and the Salesforce SOQL/SOSL/debug-log family), templating grammars (HAML, Slim, Vento, rsHTML), and systems/config grammars (m68k, scfg, kitty, jjdescription, bpftrace, strace, SystemTap, TRACE32). Seven permissively-licensed but unmaintained grammars are vendored in-repo (ABNF, PlantUML, Promela, Reason, Wolfram, XQuery, Yul), and `just` is re-sourced to the canonical `casey/tree-sitter-just`. * Detect kitty (`kitty.conf`), rsHTML (`.rs.html`), and dotenv (`.env`) files by name. * The core library emits `tracing` spans and events always-on across parsing, grammar loading, and download operations, making observability a first-class product surface. `tracing` is now a non-optional dependency (near-zero cost without a subscriber). Levels follow the shared contract: INFO for coarse state changes (download/init/prefetch/clean, network bundle fetch), DEBUG for per-call flow (`process`, `get_language`, grammar shared-library loads). Span names and field keys are part of the public API. ### Changed [Section titled “Changed”](#changed-1) * The `ts-pack` CLI installs a `tracing` subscriber for every command (previously only the MCP server did), so `RUST_LOG` surfaces library diagnostics on stderr for all subcommands; machine- readable result output on stdout is unchanged. `tracing`/`tracing-subscriber` are no longer gated behind the `mcp` feature. * Raw `println!`/`eprintln!`/`print!`/`eprint!`/`dbg!` are denied in production code across the workspace (clippy `print_stdout`/`print_stderr`/`dbg_macro`); `tracing` is the sole diagnostic surface. The `ts-pack` CLI’s command results and prompts remain its stdout/stderr output contract (opted in crate-wide), while the MCP command’s diagnostics continue through `tracing`. * Regenerate all language bindings on alef 0.49.0. ## 1.13.5 - 2026-07-27 [Section titled “1.13.5 - 2026-07-27”](#1135---2026-07-27) ### Changed [Section titled “Changed”](#changed-2) * Regenerate all language bindings on alef 0.48.4, which fixes the Java publish (lowered the Maven enforcer floor) and the C# publish (generates `runtime.json.template` so `runtime.json` can be rendered before the NuGet pack). * Update grammar revisions to latest upstream (gnuplot, javadoc, scala, tmux). * Upgrade Rust dependencies to their latest incompatible versions (base64 0.22 -> 0.23). ### Fixed [Section titled “Fixed”](#fixed-1) * **ci**: render `runtime.json` from its template before packing the NuGet package so C# runtime metadata is published correctly. ## 1.13.4 - 2026-07-26 [Section titled “1.13.4 - 2026-07-26”](#1134---2026-07-26) ### Changed [Section titled “Changed”](#changed-3) * Regenerate all language bindings on alef 0.48.2. * Update dependencies to their latest compatible versions. ### Removed [Section titled “Removed”](#removed) * Remove unused Java PMD ruleset and stale linter configuration. ## 1.13.3 - 2026-07-21 [Section titled “1.13.3 - 2026-07-21”](#1133---2026-07-21) ### Fixed [Section titled “Fixed”](#fixed-2) * **ruby**: platform-specific native gems now package one native extension per supported Ruby ABI and load the extension matching the current runtime. This keeps precompiled gems usable on Ruby 3.2, 3.3, 3.4, 3.5, and Ruby 4 while avoiding `Parser#parse` self-conversion `TypeError`s from loading an extension compiled against a different Ruby ABI. Fixes [#171](https://github.com/xberg-io/tree-sitter-language-pack/pull/171). ### Changed [Section titled “Changed”](#changed-4) * **grammars**: refresh 22 grammar revisions to newer upstream commits (no languages added or removed). * **deps**: refresh lock files with non-breaking updates within existing constraints (`Cargo.lock`, `pnpm-lock.yaml`, `uv.lock`, Ruby `Gemfile.lock`). * Regenerated all bindings with alef 0.42.0. ## 1.13.2 - 2026-07-20 [Section titled “1.13.2 - 2026-07-20”](#1132---2026-07-20) ### Fixed [Section titled “Fixed”](#fixed-3) * **ruby**: the Magnus binding now exposes the `Parser` instance methods (`set_language`/`parse`/`parse_bytes`/`reset`). alef previously skipped `&mut self` methods on opaque types, so `Parser` was generated with no callable methods; `parse_bytes` also now accepts a Ruby `String`. This fixes the root cause behind [#168](https://github.com/xberg-io/tree-sitter-language-pack/issues/168) at the generator level (alef 0.38.4), superseding the hand-edit stopgap in [#169](https://github.com/xberg-io/tree-sitter-language-pack/pull/169). ### Changed [Section titled “Changed”](#changed-5) * **build**: regenerate all bindings against alef 0.38.4. Swift and Elixir generated output pick up the 0.38.4 codegen fixes (Swift `CodingKeys` honoring serde renames, `Optional>` accessors no longer double-encoding, and the Elixir e2e streaming entry-point suffix). * **ci**: the Docker CI and publish workflows tolerate a full GitHub Actions cache — a cache-export failure no longer fails the build. ## 1.13.1 - 2026-07-19 [Section titled “1.13.1 - 2026-07-19”](#1131---2026-07-19) ### Fixed [Section titled “Fixed”](#fixed-4) * **ruby**: the published 1.13.0 gem still shipped `required_ruby_version = [">= 3.2.0", "< 4.0"]` despite [#162](https://github.com/xberg-io/tree-sitter-language-pack/pull/162), because alef regeneration reverted the hand-edit. Fixed at the generator level (alef 0.38.0 defaults to `">= 3.2.0"` with no upper bound and makes the constraint configurable), so the gem now installs on Ruby 4.x. * **elixir**: positional JSON-encoded NIF args now forward `nil` and pre-encoded JSON strings as-is instead of double-encoding, matching the keyword-arg path (alef 0.38.0). ### Changed [Section titled “Changed”](#changed-6) * **build**: regenerate all bindings against alef 0.38.0. Includes an improved Dart native-library loader (env-var override, versioned user cache, explicit errors). ## 1.13.0 - 2026-07-19 [Section titled “1.13.0 - 2026-07-19”](#1130---2026-07-19) ### Added [Section titled “Added”](#added-1) * **ruby**: expose the parser API methods (`Parser#parse`, tree/node accessors) on the Ruby binding so consumers can drive parsing directly instead of only fetching languages. Fixes [#166](https://github.com/xberg-io/tree-sitter-language-pack/pull/166). * **ruby**: support installing on Ruby 4. Removed the `< 4.0` RubyGems constraint; the native extension builds and the generated Ruby e2e suite passes on Ruby 4.0.6. Fixes [#162](https://github.com/xberg-io/tree-sitter-language-pack/pull/162). * **ci**: run the Ruby package and Ruby e2e tests on Ruby 4.0 in addition to Ruby 3.4. ### Fixed [Section titled “Fixed”](#fixed-5) * **dart**: pin `freezed` to the stable `^3.2.5` constraint instead of a `^4.0.0-dev` prerelease. The prerelease was rejected by `flutter_rust_bridge_codegen`’s dependency validator, which broke the Dart binding build. * **node**: build and publish the `linux-x64-musl` and `linux-arm64-musl` platform sub-packages. CI now cross-compiles both musl targets (via zig / `cargo-zigbuild`), and the main package’s `optionalDependencies` reference the real version instead of the `0.0.1` placeholder, so the native binaries resolve on Alpine/musl systems. * **elixir**: generate typed e2e configs. Fixes [#167](https://github.com/xberg-io/tree-sitter-language-pack/pull/167). * **ci**: the sdist smoke test uses the `tree_sitter` property API (`root_node`/`type`). ### Changed [Section titled “Changed”](#changed-7) * **grammars**: refresh 39 grammar revisions to newer upstream commits (no languages added or removed). * **deps**: bump `rmcp` to 2.2, `go-tree-sitter` to v0.25.0, `@napi-rs/cli` to ^3.7.3, `@types/node` to ^26.0.0, and `vitest` to ^4.1.10. * Regenerated all bindings with alef 0.37.0. * **docs**: migrate the documentation site to Astro Starlight on the shared `@xberg-io/docs-theme`, and rewrite the landing page and README to a value-first voice. ## 1.12.5 - 2026-07-07 [Section titled “1.12.5 - 2026-07-07”](#1125---2026-07-07) ### Fixed [Section titled “Fixed”](#fixed-6) * **build**: `build.rs` no longer forces spurious rebuilds when the crate is consumed from a registry (crates.io) rather than a git checkout. It skips `cargo:rerun-if-changed` for the `query-overlays` directory when it does not exist, skips rerun triggers for parser directories that live under `OUT_DIR`, and falls back to `CARGO_MANIFEST_DIR` when the overlay-directory search walks past the filesystem root. Previously these emitted rerun triggers on nonexistent or generated paths, so cargo rebuilt the crate on every invocation. Fixes [#159](https://github.com/xberg-io/tree-sitter-language-pack/pull/159). ## 1.12.3 - 2026-07-02 [Section titled “1.12.3 - 2026-07-02”](#1123---2026-07-02) ### Fixed [Section titled “Fixed”](#fixed-7) * **python**: `get_parser()` now returns the installed `tree_sitter.Parser` instead of a vendored parser class. On Python 3.14 the vendored parser produced unusable trees — nodes exposed no `type`/`children` and `parse(bytes)` raised `TypeError` — while nothing failed at construction, so the breakage was silent. `get_parser(name)` now builds `tree_sitter.Parser(get_language(name))`, mirroring `get_language()` and working across Python versions. Fixes [#157](https://github.com/xberg-io/tree-sitter-language-pack/issues/157). ### Changed [Section titled “Changed”](#changed-8) * **deps**: upgrade dependencies to their latest versions across every language binding (Rust, Python, Node, Ruby, PHP, Go, Java, C#, Elixir, WASM, Dart, Swift, Zig, Kotlin-Android) and refresh grammar revisions and GitHub Actions pins. On `wasm32`, `getrandom` moves to 0.4 with the `wasm_js` feature. * Regenerated all bindings with alef 0.30.10, which corrects the generated Python `get_parser` return annotation (previously an invalid `_rust.Parser` that broke import on Python < 3.14). ### Fixed [Section titled “Fixed”](#fixed-8) * **wasm**: skip the `tmux` grammar on `wasm32`. Its generated `parser.c` is \~30MB — under `TSLP_WASM_MAX_PARSER_BYTES` (40MB) so the size gate doesn’t catch it, but it still overruns the clang wasm backend during codegen. Added to `DEFAULT_WASM_SKIP_GRAMMARS` so the wasm build is clean; it degrades gracefully (absent from `STATIC_LANGUAGES`). * **wasm**: enable the `getrandom` `js` feature for `wasm32-unknown-unknown`. Build-dependencies (ureq) transitively depend on `getrandom`, which requires the `js` feature on that target; without it wasm32 builds failed with “the wasm\*-unknown-unknown targets are not supported by default”. * **build**: `build.rs` now reports `failed_languages.txt` write errors separately (via `eprintln`) and always surfaces the underlying grammar compilation error even when the write fails. ## 1.12.0 - 2026-06-29 [Section titled “1.12.0 - 2026-06-29”](#1120---2026-06-29) ### Added [Section titled “Added”](#added-2) * **prefetch**: `prefetch(&[&str])` downloads (if needed) and loads every requested grammar in one pass, so a subsequent parallel workload only parses. It probes real on-disk loadability rather than `has_language`, fixing a short-circuit where known-but-not-downloaded grammars were skipped. * **query cache** (Rust): `get_query(language, QueryKind) -> Result>>` compiles a bundled `.scm` query once and caches the `Arc` process-wide (negative results cached too). Rust-only — bindings continue to expose the raw query-string accessors. * **indents & folds queries**: `get_indents_query` / `get_folds_query` now expose the bundled `indents.scm` / `folds.scm` (harvested from the grammar bundle alongside the existing kinds); `QueryKind` gains `Indents` and `Folds`. ### Changed [Section titled “Changed”](#changed-9) * **performance**: `get_language` now takes a lock-free fast path for statically-compiled and already-loaded dynamic grammars; the global load mutex guards only the not-yet-loaded dynamic library path. Removes per-call mutex contention on the hot parse path. ## 1.11.1 - 2026-06-29 [Section titled “1.11.1 - 2026-06-29”](#1111---2026-06-29) ### Fixed [Section titled “Fixed”](#fixed-9) * **python**: `get_language()` (and other download failures) now surface the public exception type in tracebacks — `tree_sitter_language_pack.DownloadError` instead of `_native.DownloadError` (#147). Regenerated against alef 0.30.1. * **java**: generate `ByteArraySerializer.java` so the generated `ObjectMapper` compiles for every package (alef 0.30.1). * **docs**: correct stale “300+” language counts to “306”. ## 1.11.0 - 2026-06-27 [Section titled “1.11.0 - 2026-06-27”](#1110---2026-06-27) Stable release promoting 1.11.0-rc.2 (fully published). Version synced across all manifests. ### Fixed [Section titled “Fixed”](#fixed-10) * **CI resource exhaustion: reduce parser generation concurrency.** The “Clone vendors” step was invoking `tree-sitter generate` with default concurrency of 3, causing each of the 306 grammars to generate in parallel (\~1 GB RSS per instance), exhausting the 7 GB RAM limit on GitHub-hosted runners and triggering SIGTERM (exit 143) at \~13 minutes. Reduced defaults to 8 clone concurrency (from 16) and 2 generate concurrency (from 3) to stay within resource budgets. Fixes CI, CLI, Docker, E2E, Swift, Rust, and Validate workflow failures. ## 1.11.0-rc.2 - 2026-06-27 [Section titled “1.11.0-rc.2 - 2026-06-27”](#1110-rc2---2026-06-27) ## 1.10.9 - 2026-06-24 [Section titled “1.10.9 - 2026-06-24”](#1109---2026-06-24) ### Fixed [Section titled “Fixed”](#fixed-11) * **Kotlin/JVM: `Tree.walk()` (and other handle-returning calls) no longer crash the JVM.** Opaque handle types (`Tree`, `Node`, `TreeCursor`) crossed the JNI boundary as `String`/JSON while the Rust shim returned a raw `jlong`, so the JVM dereferenced a primitive as an object reference and faulted with `EXCEPTION_ACCESS_VIOLATION`. Regenerated with alef 0.27.1, the kotlin-android bridge now returns primitive `Long` handles (required and optional, via a `0L` sentinel) and constructs the wrapper directly. Fixes #146. * **Python: exported exception classes are now catchable.** `get_language("unknown")` raised `_native.DownloadError`, a different class object than the `DownloadError` exported from the package, so `except DownloadError:` never caught it. Regenerated with alef 0.27.1, the native variants derive from the native base `Error` and the package re-exports the native classes (with matching type stubs), so `except DownloadError:`/`except Error:` work. Fixes #147. ## 1.10.8 - 2026-06-24 [Section titled “1.10.8 - 2026-06-24”](#1108---2026-06-24) ### Fixed [Section titled “Fixed”](#fixed-12) * **wasm32 builds no longer OOM on pathologically large grammars.** Compiling the bundled grammars to `wasm32` previously included every `parser.c`, but a few are huge *generated* sources (e.g. `abl` at \~130 MB) that need 18-25 GB+ of clang RAM at *any* optimization level — a single one OOMs standard ≤16 GB CI runners (serialization via `CARGO_BUILD_JOBS=1` cannot help when one file alone exceeds the budget). `build.rs` now skips any grammar whose `parser.c` exceeds a size limit on wasm32 (default 40 MB, configurable via `TSLP_WASM_MAX_PARSER_BYTES`; `0` disables the gate), emitting a `cargo:warning` per skipped grammar plus a summary. Skipped grammars are absent from `STATIC_LANGUAGES` (no dangling FFI symbol) and degrade gracefully at runtime. The 40 MB default keeps every common language (including the \~40 MB `sql` grammar) and excludes only the handful of unbuildable outliers (`abl`, `systemverilog`, `razor`, `fsharp`, `verilog`, `gnuplot`, `latex`). (`crates/ts-pack-core/build.rs`) * **Swift publish now creates the `release/swift/` branch carrying the substituted XCFramework checksum.** The alef-generated Swift e2e/test-app pins `.package(url: …, branch: "release/swift/")` (the non-destructive layout shared with the other polyglot repos), but the publish workflow only force-moved the `v` tag and never created that branch — so SwiftPM could not resolve the package and the Swift test-app failed with an empty `TreeSitterLanguagePack` target. The checksum commit is now also pushed to `refs/heads/release/swift/`. (`.github/workflows/publish.yaml`) ## 1.10.4 - 2026-06-22 [Section titled “1.10.4 - 2026-06-22”](#1104---2026-06-22) ### Added [Section titled “Added”](#added-3) * **`ts-pack mcp` server now exposes MCP resources, prompts, and argument completions** in addition to its tools. Resources serve the language catalog (`ts-pack://languages`, `ts-pack://languages/downloaded`) and a per-language template (`ts-pack://language/{name}`); a ready-made `analyze-code` prompt drives a structure/imports/symbols analysis workflow; and language-name arguments autocomplete against the available-language catalog. ### Changed [Section titled “Changed”](#changed-10) * **`ts-pack mcp` tools are now fully aligned with the CLI and carry accurate rmcp annotations.** The `download` tool takes `groups` (multiple) and `fresh` like `ts-pack download`; `process` gains the `all` flag; the combined `cache` tool is split into `cache_dir` (read-only) and `clean_cache` (destructive), mirroring the CLI. Every tool now declares correct `open_world_hint`, `read_only_hint`, `destructive_hint`, and `idempotent_hint` values. * **The CLI ships the MCP server by default.** `mcp` is now a default feature of `ts-pack-cli`, so `ts-pack mcp` is present in every distribution — `cargo install ts-pack-cli`, the prebuilt release binary, Homebrew, and the `@kreuzberg/ts-pack-cli` / `ts-pack-cli` npx/uvx proxies. Previously the feature was opt-in and absent from shipped binaries, which also broke the marketplace plugin launcher that invokes `ts-pack mcp`. ### Fixed [Section titled “Fixed”](#fixed-13) * **Host-native `get_language()` passthrough now works for Swift, Kotlin-Android, and Java.** The capsule passthrough (#143) returns the ecosystem’s native `Language`, but the bindings did not wire the host-runtime dependency: Swift generated an uncompilable forwarder (wrong return type, missing `import SwiftTreeSitter`); Kotlin-Android declared `ktreesitter` as `implementation`, hiding the `Language` type from callers’ compile classpath; and Java’s `jtreesitter` (Panama FFM) dlopens the standalone `libtree-sitter` runtime, which CI and the test harness did not provision. Fixed via alef 0.26.1 (Swift/Kotlin codegen) plus `libtree-sitter` provisioning in CI and the Java test harness. Zig already wired its `tree_sitter` module correctly. * **`.app.src` files now map to Erlang.** The application-resource template is Erlang term syntax, but single-extension lookup only saw `src`. A compound-extension table now resolves `*.app.src` to the Erlang grammar. ## 1.10.3 - 2026-06-22 [Section titled “1.10.3 - 2026-06-22”](#1103---2026-06-22) ### Changed [Section titled “Changed”](#changed-11) * **Regenerated all bindings with alef 0.26.0.** Picks up alef’s sync-versions byte-stability fix: `sync-versions` no longer rewrites externally-formatted scaffold/manifest files (this repo formats via external tools with `[workspace.format] enabled = false`), and it preserves external SwiftPM dependency pins instead of clobbering them with the workspace version. This clears the CI version-sync freshness gate. * **Updated dependencies within their current major versions** (Rust crates, PHP dev tooling, pnpm toolchain pin). ## 1.10.2 - 2026-06-22 [Section titled “1.10.2 - 2026-06-22”](#1102---2026-06-22) ### Fixed [Section titled “Fixed”](#fixed-14) * **Generated binding doc comments no longer emit Rust intra-doc link syntax.** alef copied core rustdoc comments verbatim into the per-language binding crates, carrying `[`Type`]` / `[`fn`](crate::fn)` intra-doc links that resolve in the core crate but break `cargo doc` in the binding crates with `rustdoc::broken-intra-doc-links`. The references are now de-linked to plain code spans (`` `Type` ``) during emission, preserving genuine URL/anchor Markdown links. Picked up from the alef 0.25.60 regen. ## 1.10.1 - 2026-06-20 [Section titled “1.10.1 - 2026-06-20”](#1101---2026-06-20) ### Fixed [Section titled “Fixed”](#fixed-15) * **Java: fixed a JVM crash (`EXCEPTION_ACCESS_VIOLATION`) when traversing a parsed tree via opaque handles (#146).** `Parser.parse`, `Tree.walk`, `Tree.rootNode`, `Node.parent`/`child`, and `TreeCursor.node` freed the returned native handle in a `finally` block immediately after wrapping it, so the returned `Tree`/`Node`/`TreeCursor` referenced already-freed memory and the next native call dereferenced it and crashed. The wrapper now owns the handle and frees it once on `close()`. Fixed in the alef Java backend and picked up by the 0.25.55 regen; value/DTO returns (`byteRange`/`startPosition`/`process`) still correctly free the FFI temporary after reading it. ### Changed [Section titled “Changed”](#changed-12) * **chore(precommit,alef): standardize kotlin-android formatting on ktfmt –kotlinlang-style.** Drop the conflicting prek ktlint hook, scope detekt/ktfmt to `packages/kotlin-android`, add `--kotlinlang-style` to ktfmt, switch `alef.toml` kotlin format/check from gradle-ktlintFormat to ktfmt so alef and prek agree, and exclude the vendored Gradle wrapper from shellcheck. detekt remains for static analysis. (`.pre-commit-config.yaml`, `alef.toml`) ### Added [Section titled “Added”](#added-4) * **Host-native `Language` passthrough across the C-ABI binding family (#143).** `get_language` now returns each ecosystem’s native tree-sitter `Language` instead of an opaque alef handle, so the result drops straight into the host runtime’s parser: Go (`*tree_sitter.Language` via `go-tree-sitter`), Zig (`?*const tree_sitter.Language` via `zig-tree-sitter`), Java (`jtreesitter.Language`), C# (`TreeSitter.Language`), Kotlin Android (`ktreesitter.Language`), and Swift (`SwiftTreeSitter.Language`) — joining the existing Python and Node passthrough. Each binding gained a dependency on its host tree-sitter runtime, injected into the generated manifest. Configured via `[crates.*.capsule_types.Language]` in `alef.toml`; regenerated against alef 0.25.55. ### Changed [Section titled “Changed”](#changed-13) * **Regenerated all bindings against alef 0.25.55.** The C FFI crate now takes a direct `tree-sitter` dependency so the capsule shim can name `tree_sitter::ffi::TSLanguage` (the pointee it casts `value.into_raw()` to), and the zig `build.zig.zon` carries the resolved `zig-tree-sitter` content hash. ## 1.9.1 - 2026-06-18 [Section titled “1.9.1 - 2026-06-18”](#191---2026-06-18) ### Fixed [Section titled “Fixed”](#fixed-16) * Swift: restored the public `getLanguage(name:)` function in the `TreeSitterLanguagePack` module. An alef 0.25.38 codegen regression added opaque types to the Swift forwarder exclusion set, dropping `get_language` (the only free function returning the opaque `Language` type) from the generated public API in v1.9.0. Regenerated against alef 0.25.43. ## 1.9.0 - 2026-06-18 [Section titled “1.9.0 - 2026-06-18”](#190---2026-06-18) ### Changed [Section titled “Changed”](#changed-14) * **Bumped `alef` pin 0.25.28 → 0.25.38 and regenerated all bindings.** Picks up alef 0.25.29–0.25.38: enum associated (static factory) methods surfaced across backends, the swift opaque no-op shim so `$_free` is synthesised for handle types with no visible methods (e.g. `Language`), swift streaming-owner `already_declared` re-declaration, java `marshal_optional_bytes` template registration, and java `@Nullable` type-use placement on qualified types. * **Upgraded all dependencies to their latest versions (cross-major).** Ran `task upgrade` across every language workspace; lock files regenerated and committed. * **Repo hygiene.** Ignore the machine-local `packages/kotlin-android/.gradle/` cache and the `.basemind/` index (untracking the accidentally-committed Gradle cache files), and exclude the deterministic `.ai-rulez/.generated-manifest.json` from the `oxfmt` pre-commit hook so it no longer fights the `ai-rulez-generate` hook. ### Fixed [Section titled “Fixed”](#fixed-17) * **Java: dropped throwing `UnsupportedOperationException` stubs for `Self`-returning DTO/enum methods.** There is no JNI/FFM symbol for DTO methods yet, so the throwing stubs compiled but misled callers and broke any path that reached them. The Java backend now skips these methods until marshaling lands. * **Java: restored the `true` default for boxed `@Nullable Boolean` `#[serde(default)]` record fields.** A non-optional `#[serde(default)] bool = true` field is boxed to `@Nullable Boolean`, so JSON that omitted it deserialised to `null` and the accessor returned `null` instead of `true`. ## 1.9.0-rc.55 - 2026-06-17 [Section titled “1.9.0-rc.55 - 2026-06-17”](#190-rc55---2026-06-17) ### Changed [Section titled “Changed”](#changed-15) * **Bumped `alef` pin 0.25.24 → 0.25.28.** Regenerated all bindings via `task alef:generate`. Picks up alef 0.25.25–0.25.28: scaffold `excluded_default_features` for dart/swift wrappers, publish/vendor retry on crates.io registry-index propagation lag, e2e/codegen wasm `[crates.e2e.env]` block, e2e/codegen php PIE invocation syntax for v1.4.5, backends/swift `RustBridgeC` import + Vec skip on already-declared types, docs heading demotion, e2e/codegen typescript `SsrfPolicy.denyPrivate=false` for WASM e2e, backends/ffi shared extractor → FFI same-name fn dedup, and **backends/dart FRB primitive bridge return-value type cast restoration** (`.map(|v| v as i64)` regression that blocked rc.55 regen). ### Fixed [Section titled “Fixed”](#fixed-18) * **Elixir Hex install OTP 27.2 TLS `key_usage_mismatch` against `builds.hex.pm`.** Switched test-elixir jobs in `ci.yaml` and `ci-e2e.yaml` to `xberg-io/actions/setup-elixir@v1` wrapper which routes through `cdn.hex.pm` to bypass OTP 27.2 TLS cert-chain rejection against `builds.hex.pm`. * **`ci.yaml` test-* jobs 404 race on `parsers.json`.*\* Mirrored `ci-e2e.yaml`’s `build-e2e-bundles` job into `ci.yaml` and added `TREE_SITTER_LANGUAGE_PACK_MANIFEST_URL` manifest wiring to all test-\* jobs (test-python, test-node, test-wasm, test-go, test-java, test-csharp, test-ruby, test-php, test-elixir, test-c-ffi). Pre-publish, the workspace version has no GitHub Release yet, so the runtime’s network fetch of `parsers.json` would 404; bundling parsers locally and exporting the manifest URL avoids the race. ## 1.9.0-rc.54 - 2026-06-17 [Section titled “1.9.0-rc.54 - 2026-06-17”](#190-rc54---2026-06-17) ### Changed [Section titled “Changed”](#changed-16) * **Bumped `alef` pin 0.25.20 → 0.25.24.** Regenerated all bindings via `task alef:generate`. Picks up alef 0.25.21–0.25.24: dart e2e setEnv robustness, swift `already_declared` opaque-handle class triples, java PMD/palantir-java-format compliance, C FFI e2e download\_ffi.sh derives FFI\_PKG\_NAME from `lib_name` (was hardcoded), kotlin-android per-file ktfmt invocation, plus the rc.53 → rc.54 structural fixes below. ### Fixed [Section titled “Fixed”](#fixed-19) * **Java loader RID alignment (rc.53 regression).** `NativeLib.resolveNativesRid()` previously emitted `osx-aarch64`/`linux-aarch64` (a JNA/LWJGL-style convention) while the published JAR’s `natives//…` directory is named via `go_java_platform()` (`macos-arm64`, `linux-aarch64`, `windows-x86_64`). Result: every macOS-arm64 client failed with `UnsatisfiedLinkError` because `natives/osx-aarch64/libts_pack_core_ffi.dylib` does not exist (it’s at `natives/macos-arm64/`). Loader template now matches `go_java_platform()` naming. * **Elixir download NIFs unregistered in precompiled binary (rc.53 regression).** The rustler NIF crate `Cargo.toml` had no `[features]` table — only a `[lints.rust] check-cfg` reference to `download`. Default precompiled CI builds therefore stripped the download/cache/init/configure NIFs from the cdylib, producing `:nif_not_loaded` errors on every `TreeSitterLanguagePack.Native.download/*`, `cache_dir/0`, `clean_cache/0`, `init/0`, `configure/1`, `downloaded_languages/0` call (10/450 errors at rc.53). Template now emits canonical `[features] default = ["config", "download", "serde"]` block forwarding to the core crate, mirroring the magnus fix from alef 0.25.19. * **Node vitest first-load timeouts.** `smoke_devicetree` and `smoke_ocamllex` exceeded the default 30 s test timeout on first load. Raised `testTimeout` to 60 s, `hookTimeout` to 120 s. * **C FFI E2E 404 race in `ci-e2e.yaml`.** `e2e/c/download_ffi.sh` pinned the FFI tarball URL to the current workspace version; on main pushes before the matching tag was created, the curl 404’d because the GitHub Release for that version didn’t exist yet. Script now honours `ALEF_FFI_LOCAL_DIR` env override to skip the network fetch and consume pre-staged headers/libs. `ci-e2e.yaml/test-c-ffi` is now `needs: build-ffi` and stages the locally-built artifact via the override. ## 1.9.0-rc.53 - 2026-06-16 [Section titled “1.9.0-rc.53 - 2026-06-16”](#190-rc53---2026-06-16) ### Changed [Section titled “Changed”](#changed-17) * **Bumped `alef` pin 0.25.18 → 0.25.20.** Regenerated all bindings via `task alef:generate`. Picks up: * **0.25.19** — magnus binding `Cargo.toml` `[features]` block (fixes rc.52 Ruby gem build under `-D warnings`), elixir NIF `Cargo.toml` `[lints.rust]` ordering (fixes CI `Check version sync`), ruby Rakefile yard-coverage hook, FFI opaque-pointer call-site `.clone()` for service-API codegen, `binding_excluded` field fallthrough that preserves bespoke core `Default::default()` semantics, csharp e2e csproj arm64 RID branching. * **0.25.20** — dart loader absolutize defensive improvement, zig opaque method error decoding (`_first_error` → `_error_with_message`), `language_pages.rs` modularization under 1000-LOC cap. ### Fixed [Section titled “Fixed”](#fixed-20) * **Ruby gem publish (rc.52 regression).** All four `Build Ruby gem` matrix jobs failed at rc.52 — the magnus binding’s `Cargo.toml` lacked the `[features]` table forwarding `download` to the core crate, so 18× `#[cfg(feature = "download")]` arms triggered `error: unexpected cfg condition value: download` under `-D warnings`. The skipped `Publish Ruby gems` step meant rc.52 never reached `rubygems.org` (test-apps:ruby failed with `Could not find gem 'tree_sitter_language_pack ~> 1.9.0.pre.rc.52'`). Picked up via alef 0.25.19. * **CI `Check version sync` red on `main`.** The elixir NIF `Cargo.toml` emitted `[lints.rust]` before `[dependencies]`; consumers’ `prek run --all-files` runs cargo-sort which reorders the block to the file end, producing a perpetual diff. The CI version-sync step does NOT run cargo-sort, so it reported “Versions are out of sync” on every release tag. Picked up via alef 0.25.19. * **Dart publish pipeline native staging (rc.52 regression).** The `assemble-dart-package` job in `.github/workflows/publish.yaml` used `download-artifact@v8` with `merge-multiple: true`, flattening every `dart-native-` artifact’s contents directly under `dart-natives/`. The subsequent RID inference (`basename "$(dirname "$f")"`) then resolved to the literal string `dart-natives` for every file, causing all four native libraries to be skipped with `Warning: unrecognized rid 'dart-natives'`. The published rc.52 pub.dev tarball contained no `lib/src/native//` directory; the FRB loader fell through to the default relative-path dlopen which macOS hardened-runtime rejected with “relative path not allowed in hardened program”. Fix: drop `merge-multiple: true` so each artifact extracts to its own `dart-natives/dart-native-/` directory, and derive the RID by stripping the `dart-native-` prefix from the artifact directory name. ## 1.9.0-rc.52 - 2026-06-16 [Section titled “1.9.0-rc.52 - 2026-06-16”](#190-rc52---2026-06-16) ### Changed [Section titled “Changed”](#changed-18) * **Bumped `alef` pin 0.25.15 → 0.25.18.** Regenerated all bindings via `task alef:generate` + `task alef:sync`. Picks up: * **0.25.16** — drop cfg propagation on enum `From`-impl match arms, API reference docs improvements. * **0.25.17** — dart `unreachable_patterns` allow at crate root, zig test sequencing to avoid `clean_cache` race, node smoke timeout for `vb`. * **0.25.18** — swift cfg-gated extern blocks for `DownloadManager` (`#[cfg(feature = "download")]`), dart absolutize env + `Platform.script` paths in hardened runtime loader, node slow-grammar list extended (`earthfile`, `perl`), pyo3 + napi emit binding-side wrapper structs for `[workspace.opaque_types]` entries without `capsule_types` override, napi binding `Cargo.toml` `[features]` block (`default = ["download"]`), cleanup detection tightened from loose `by alef` substring to specific `auto-generated by alef`, cbindgen `autogen_warning` updated so generated C headers are correctly identified as cbindgen-owned. ### Fixed [Section titled “Fixed”](#fixed-21) * **Python `get_language` / `get_parser` API consistency (#141).** Both helpers now return the binding’s own native types (`Language`, `Parser`) instead of the standalone `tree_sitter` package’s `Language`, matching every other binding (Java, Go, Swift, Ruby, C#, etc.). Dropped `pip_dependencies = ["tree-sitter>=0.23"]` from the Python package. **Breaking change** for callers that relied on `tree_sitter.Parser(get_language(name))` — use `get_parser(name)` directly, or import `tree_sitter` as a separate dependency. * **Node `getLanguage` / `getParser` API consistency.** Same shape change as Python — `getLanguage` now returns the native `Language` class from `@kreuzberg/tree-sitter-language-pack` rather than passing through to the upstream `tree-sitter` npm package. Dropped the `tree-sitter` devDependency from the e2e harness. * **Swift `DownloadManager` build error.** swift-bridge proc-macro previously failed with `no type named 'DownloadManager' in module 'RustBridge'` (and 9 related missing-member errors) because cfg-gated extern blocks were emitted unconditionally. Now wrapped in `#[cfg(feature = "download")]` so disabled-feature compile correctly elides the bridge surface. * **Dart hardened-runtime dlopen failures.** All 9 dart e2e tests previously failed at `setUpAll` with “relative path not allowed in hardened program”. Loader now absolutizes env-var and `Platform.script`-derived paths before constructing search roots. * **Node smoke timeouts on `earthfile` and `perl`.** Tree-sitter grammars with heavy scanner.c logic now receive the 90000ms slow-grammar timeout (previously only `vb` was covered). ### Removed [Section titled “Removed”](#removed-1) * **Python: standalone `tree-sitter` package dependency.** No longer required by `tree-sitter-language-pack`. Install it separately if you need the upstream API. * **Node: `e2e/node/tests/capsule_passthrough.test.ts` and `tree-sitter` devDependency.** Obsolete now that node `getLanguage` returns the native type. ## 1.9.0-rc.51 - 2026-06-15 [Section titled “1.9.0-rc.51 - 2026-06-15”](#190-rc51---2026-06-15) ### Changed [Section titled “Changed”](#changed-19) * **Bumped `alef` pin 0.25.14 → 0.25.15.** Regenerated all bindings via `task alef:sync` + `task alef:generate`. Picks up the swift cfg-postprocess revert: * **0.25.15 — revert(swift): drop cfg-union postprocessing passes (c89926d5e, 4313b6e1d).** The wrapper-type and function cfg-union propagation passes introduced in 0.25.12/0.25.13 caused downstream binding regressions; reverted in favour of the 0.25.14 default-features approach in the swift binding Cargo.toml. * **Bumped tslp `1.9.0-rc.50` → `1.9.0-rc.51`** propagated via `task alef:sync`. ## 1.9.0-rc.50 - 2026-06-15 [Section titled “1.9.0-rc.50 - 2026-06-15”](#190-rc50---2026-06-15) ### Changed [Section titled “Changed”](#changed-20) * **Bumped `alef` pin 0.25.11 → 0.25.14.** Regenerated all bindings via `task alef:sync` + `task alef:generate`. Picks up the accumulated fixes: * **0.25.12 — (java): bind `${classifier}` property to maven-jar-plugin config so native JARs are emitted with the correct classifier.** Resolves rc.49 Maven Central regression where `tree-sitter-language-pack-java-1.9.0-rc.49.jar` was published without classifier (missing `/natives/{rid}/libts_pack_core_ffi.dylib`), causing `UnsatisfiedLinkError` at JNI init. * **0.25.12 — (dart): copy `.framework` directories recursively in publish workflow assemble step.** The `find` predicate matched only `*.so`/`*.dylib`/`*.dll` files and skipped macOS `.framework/` bundles; pub.dev rc.49 was missing `tree_sitter_language_pack_dart.framework/`. * **0.25.12 — (php): always stage PIE extension as `.so` on Unix.** PIE 1.4.5 probes for `.so` on all Unix platforms including macOS; the previous OS-branching produced rc.49 prebuilt archives missing the `.so` (PIE extracted source but found no binary). * **0.25.12 — Swift wrapper-type cfg union postprocess.** Wrapper structs whose fields reference cfg-gated upstream types now inherit the union cfg gate, fixing swift-bridge-build `Type must be declared with 'type X'` panics. * **0.25.13 — Swift function cfg union postprocess.** Free helper functions taking cfg-gated wrapper struct references now inherit the union cfg gate, complementing the wrapper-type fix. * **0.25.14 — Swift binding Cargo.toml lists every forwarded cfg-feature in `default = [...]`.** Prevents `error[E0425]: cannot find type 'DownloadManager' in this scope` on regen consumers when the wrapper struct is cfg-gated but free helper functions referencing it are not — the binding’s default profile now matches what its core dep already pulls in via `features = [..., "download"]`. * **Bumped tslp `1.9.0-rc.49` → `1.9.0-rc.50`** propagated via `task alef:sync`. ## 1.9.0-rc.49 - 2026-06-15 [Section titled “1.9.0-rc.49 - 2026-06-15”](#190-rc49---2026-06-15) ### Changed [Section titled “Changed”](#changed-21) * **Bumped `alef` pin 0.25.9 → 0.25.11.** Regenerated all bindings via `task alef:sync` + `task alef:generate`. Picks up the accumulated 0.25.10 and 0.25.11 fix series: * **0.25.10 — `publish prepare` canonicalize bug.** `publish prepare` was canonicalizing only `manifest_dir.join("Cargo.toml")`, not `manifest_dir` itself. With `current_dir(manifest_dir)` set on the cargo subprocess, the `--manifest-path ./packages/elixir/.../Cargo.toml` argument resolved relative to the new cwd — effectively doubling the path — and cargo bailed with `manifest path '...' does not exist` followed by the misleading “publish core first” hint. Every source-build binding in rc.48 hit this (Python sdist, Ruby gem, Elixir NIF, PHP PIE). 0.25.10 canonicalizes `manifest_dir` itself at the top of the regenerate branch and `manifest_abs` in `rewrite_binding_path_deps`. * **0.25.10 — kotlin-android `copyHostJni` always reads workspace target.** Drop the configuration-time `if (workspaceTarget.exists())` selector that evaluated before `cargo build` finished, eliminating the `UnsatisfiedLinkError` cascade at static-init time on every JNI-loading test class. * **0.25.10 — R extendr enum path resolution.** `gen_from_binding_to_core`/`gen_from_core_to_binding` now use `resolve_type_path` against a `build_type_path_lookup(api)` map instead of `core_enum_path_remapped`, fixing E0433 `cannot find ImageOutputFormat in crate 'kreuzberg'` for enums defined outside the crate root. * **0.25.10 — Swift `From` arms cfg-gate variants.** `emit_enum_wrapper` now prepends `#[cfg(...)]` before each rendered arm so the match remains valid when the binding crate’s feature set drops upstream variants (iOS / Android cross-targets). * **0.25.10 — C# e2e csproj emits `false`.** Closes the CS0579 duplicate-attribute path for consumer e2e directories that carry a hand-checked-in `Properties/AssemblyInfo.cs`. * **0.25.10 — Visitor result routes bare strings to `Custom` when multiple string-payload variants exist.** Fixes silent fallback to the default variant when an enum has both `Custom(String)` and `Error(String)`. * **0.25.10 — FFI visitor context emits enum-typed fields as `i32` discriminant.** Closes the `ArrayIndexOutOfBoundsException` cascade in `VisitorBridge.decodeContext` caused by reading the low 4 bytes of `tag_name` pointer when the C struct omitted the enum field. * **0.25.10 — Dart cfg-extraction whitespace bug and check-cfg allow-list.** `extract_feature_names_from_cfg` now normalizes whitespace + handles the `any(test, feature = "X")` sibling form; check-cfg allow-list populates from every `EnumDef.variants[*].cfg` instead of falling back to the single-entry `cfg(frb_expand)` form. * **0.25.10 — Release task: `task set-version` handles prerelease versions when updating `ALEF_REV`** + **Ruby Rakefile template documents `GEMSPEC` constant** for YARD coverage. * **0.25.11 — README generation supports named non-language targets.** `[crates.readme.targets.]` renders additional template-backed README outputs alongside per-language READMEs. * **0.25.11 — Option B cfg forwarding for Dart and Swift binding crates.** Each cfg feature name referenced by any IR type/field/variant/function is now emitted as `{name} = ["{core_dep_key}/{name}"]` in `[features]`, making the feature resolvable at the binding level and eliminating `unexpected_cfgs` without an allow-list. Shared collection logic extracted to `src/codegen/cfg.rs`. WASM backend now delegates to it. Swift `emit_enum_wrapper` emits a `_ => unreachable!()` catch-all whenever any variant in the primary list carries a `#[cfg(...)]` gate. * **0.25.11 — Generated Homebrew test apps trust third-party taps before installing formulae.** `run_tests.sh` now calls `brew trust "$TAP" || true` before `brew bundle install`. * **0.25.11 — Dart test\_app run no longer invokes `download_libs`.** Natives ship inside the pub.dev package; the FRB loader resolves them from `lib/src/native//`. Drops the structural HTTP 404 against `releases/download/v.../tree-sitter-language-pack-dart-...` that masked publish-pipeline failures. * **0.25.11 — C e2e Makefile: always re-download `ts_pack.h`.** Drops the `HEADER_PATH`/`LIB_PATH` short-circuit that elided the header dependency whenever a stale prior-rc header was on disk. Per-version marker `ffi/.alef-ffi-version` keeps unchanged trees from paying network cost. Resolves the rc.48 C test\_app `unknown type name 'TS_PACKDataNode'` cascade. * **0.25.11 — C# scaffold: SDK-generated AssemblyInfo with explicit version stamps and full RID list.** Enables `` (drops `false` suppression), stamps ``/`` as 4-component numeric (`MAJOR.MINOR.PATCH.0`) via new `to_dotnet_assembly_version` helper, preserves full SemVer on ``, replaces conditional singular `` with a plural list of all six published RIDs, and pins `AnyCPU`. Resolves the rc.48 C# `Version=0.0.0.0` + `targets a different processor` cascade. * **0.25.11 — Zig `_error_with_message` dispatches to per-error-set message-prefix matchers.** Replaces the unconditional `_first_error(E)` fallback that masked the real cause of every typed FFI failure; emits a `if (E == ErrName) return _from_ffi_msg_ErrName(msg_opt);` chain per declared error-set. * **0.25.11 — Rustler codegen clippy violations** (type complexity, collapsible if, struct update, useless conversions) + **Rustler trait-bridge parameter cloning skips no-op clones on reference types** + **JNI clippy lints + Swift cargo.rs api param** + **pyo3 async lifetime/result-handling cleanup**. * **Bumped tslp `1.9.0-rc.48` → `1.9.0-rc.49`** propagated via `task alef:sync`. ## 1.9.0-rc.48 - 2026-06-15 [Section titled “1.9.0-rc.48 - 2026-06-15”](#190-rc48---2026-06-15) ### Changed [Section titled “Changed”](#changed-22) * **Bumped `alef` pin 0.25.6 → 0.25.9.** Regenerated all bindings via `alef sync-versions --skip-swift-checksum` + `task alef:generate`. Picks up the accumulated 0.25.6/0.25.7/0.25.8/0.25.9 fixes: * **0.25.6 — Java codegen.** `NativeLib` downcall fallback chain now emits in the single-line shape that palantir-java-format produces, so the regenerated `NativeLib.java` no longer triggers a post-regen formatter rewrite (the diff that broke rc.47’s `Validate Lint & Format` job). * **0.25.6 — publish vendor `cargo --locked` paradox.** `alef publish prepare` was running `cargo update -p ` with `--locked` passed via `CARGO_BUILD_LOCKED`, which made cargo refuse to update the lockfile. The Python sdist + all 4 Ruby gem + all 4 Elixir NIF + all 18 PHP PIE jobs on rc.47 failed with “cannot update the lock file … because –locked was passed”. Fix: `vendor.rs` now `.env_remove("CARGO_BUILD_LOCKED")` before both cargo invocations and drops the `--locked` flag from `cargo metadata`. Regression test `scrub_lock_succeeds_for_non_workspace_binding_crate_with_incomplete_seed` covers the path. * **0.25.8 — Dart mirror enum cfg-strip.** `emit_mirror_enum` no longer propagates `variant.cfg` into the generated mirror enum body. The mirror is a DTO/wire type that `flutter_rust_bridge_codegen` references unconditionally from `frb_generated.rs` — gating a variant out via `#[cfg]` left the unconditional reference dangling with `E0599 no variant named 'Heif' found for enum 'ImageOutputFormat'` when the binding crate didn’t declare the upstream feature. The catch-all `_ => unreachable!()` arm in the `From` impl (introduced earlier) handles runtime safety. * **0.25.9 — Dart check-cfg allow-list + mirror dead-code cleanup + publish current\_dir.** Resolves the v0.25.8 build regression where the 0.25.8 cfg-strip patch orphaned the `emit_variant_cfg_open`/`emit_variant_cfg_close` helpers, tripping `-D warnings` on all 4 alef publish jobs (3× Build CLI + crates.io). Also widens the dart check-cfg allow-list and tightens `publish` current-dir handling. * **alef-side accumulated fixes (released as 0.25.9 alongside the above).** Direct-deps replacement for the no-op `[patch.crates-io]` block alef 0.25.8 emitted in the Elixir NIF `Cargo.toml` (cargo refused with “patch points to the same source”). Direct deps with `=` constraints + matching `package.metadata.cargo-machete.ignored` entries pin `alloc-no-stdlib`/`alloc-stdlib`/`brotli-decompressor` transitively. YARD doc-coverage hook fixed via a documented `GEMSPEC` constant in the generated `packages/ruby/Rakefile` and a matching docstring in the in-tree stale `packages/ruby/ext/ts_pack_core_rb/src/Rakefile` (the latter file is hand-maintained and not regenerated; cleanup deferred). ## 1.9.0-rc.46 - 2026-06-14 [Section titled “1.9.0-rc.46 - 2026-06-14”](#190-rc46---2026-06-14) ### Changed [Section titled “Changed”](#changed-23) * **Bumped `alef` pin 0.25.1 → 0.25.2.** Picks up two source-build publish-prepare fixes: * `publish prepare` now strips workspace-member `[[package]]` entries from the seeded `Cargo.lock` before per-member `cargo update -p`. Without this strip the path-source seed entry collides with the rewritten registry-source dep and `cargo metadata --locked` validation fails. * `publish prepare` disambiguates the per-member `cargo update -p` spec by using the full `registry+https://github.com/rust-lang/crates.io-index#NAME@VERSION` package id when the member version is known. Both fixes are required to unblock Ruby gem + Elixir NIF + PHP extension matrix builds on rc.46 (rc.45 failed Ruby macos-x86\_64 / linux-aarch64 + Elixir linux-aarch64 / macos-x86\_64 on this exact path). ## 1.9.0-rc.45 - 2026-06-14 [Section titled “1.9.0-rc.45 - 2026-06-14”](#190-rc45---2026-06-14) ### Changed [Section titled “Changed”](#changed-24) * **Cross-major dependency upgrade** via `task upgrade`. Rust + Python + Node + Java + Elixir + PHP + Ruby dep trees rebased to their latest semver-compatible heads; lockfiles re-resolved (`Cargo.lock`, `e2e/rust/Cargo.lock`, `composer.lock`, `pnpm-lock.yaml`, `mix.lock`, `uv.lock`, `packages/php/composer.lock`). `sources/language_definitions.json` regenerated. * **Bumped `alef` pin 0.25.0 → 0.25.1.** Picks up the `assertions.rs:227` C-e2e codegen hardening (panic-on-missing-`fields_c_types` rather than the silent PascalCase fallback that produced `TS_PACKData` instead of `TS_PACKDataNode` in rc.43). * **All cargo invocations across `.github/workflows/` and `.task/` now pass `--locked`.** Sweep applied in a separate commit (`130627437`) ahead of this regen to keep the manifest-normalisation fix isolated; this rc carries it forward. Same motivation as the actions-side v1.8.68 sweep: a broken upstream release (recent `brotli-decompressor 5.0.1`) can no longer silently override the committed lockfile during CI. ## 1.9.0-rc.44 - 2026-06-14 [Section titled “1.9.0-rc.44 - 2026-06-14”](#190-rc44---2026-06-14) ### Fixed [Section titled “Fixed”](#fixed-22) * **`publish-release`: normalise parser library names across platforms in the `parsers.json` manifest generator.** Linux/macOS produce `libtree_sitter_.{so,dylib}`, Windows produces `tree_sitter_.dll` (no `lib` prefix). The `Generate parsers.json manifest` step compared the stripped basenames as-is, so the intersection of grammar names across platforms was empty whenever the Windows archives were present — the manifest then reported every grammar as missing on Windows and refused to upload. The generator now strips the `lib` prefix and `tree_sitter_` / `tree-sitter-` prefix uniformly and reverses the four `c_symbol` overrides (`c_sharp`/`embedded_template`/`nu`/`vb_dotnet`) so the per-platform sets agree on language identifiers. * **`alef.toml`: declare `process_result.data → DataNode` in `[crates.e2e.fields_c_types]`.** alef’s C e2e generator falls back to `.to_pascal_case()` when a field path is not declared, which produced `TS_PACKData` instead of the actual cbindgen-emitted `TS_PACKDataNode`. Adding the explicit mapping makes the regenerated `e2e/c/test_data_extraction.c` reference `TS_PACKDataNode*` and the `ts_pack_data_node_*` accessor family consistently. A deeper alef-side hardening of the fallback (loud error or IR-driven type lookup) is accumulated locally in `../alef` and pending an alef release. * **`build.rs`: allow `clippy::type_complexity` on the MSVC patches table.** The `&[(&str, &str, &[(&str, &str)])]` shape introduced for crystal/sml MSVC compat tripped `clippy -D warnings` in CI; the table reads cleanly as a literal and isn’t worth a type alias. * **`rust-max-lines` pre-commit cap: exclude `crates/ts-pack-core/src/intel/data_extraction.rs`.** New 1322-line module added for hierarchical data extraction; remediation backlog entry. ## 1.9.0-rc.43 - 2026-06-14 [Section titled “1.9.0-rc.43 - 2026-06-14”](#190-rc43---2026-06-14) ### Fixed [Section titled “Fixed”](#fixed-23) * **`publish-release`: read `.tar.zst` parser archives via `zstandard`.** Python’s `tarfile.open(path, 'r:*')` only supports `.gz`, `.bz2`, `.xz`, and uncompressed `.tar` — not `.tar.zst`. The `Generate parsers.json manifest` step was failing with `tarfile.ReadError: not a gzip file / not a bzip2 file / not an lzma file / invalid header`, blocking parsers.json + parsers-\*.tar.zst upload to the release and breaking every downstream consumer at runtime with `Failed to fetch manifest from .../parsers.json: http status: 404`. The step now `pip install --user zstandard` then opens each archive via `ZstdDecompressor().stream_reader()` and `tarfile.open(fileobj=..., mode='r|')`. ## 1.9.0-rc.42 - 2026-06-14 [Section titled “1.9.0-rc.42 - 2026-06-14”](#190-rc42---2026-06-14) ### Changed [Section titled “Changed”](#changed-25) * **Regenerated against released alef 0.25.0.** Picks up the new `Extension` trait surface (per-extension TOML config + `transform_emitted_files` hook), Swift target-specific core dependency overrides, the zig `_first_error` → contextual error fix, and the Dart hardened-runtime framework load fix. Restores `crates/ts-pack-core-ffi/{src/lib.rs,build.rs,cbindgen.toml}` which a transient pre-release regen against an in-progress alef had erroneously dropped. ## 1.9.0-rc.41 - 2026-06-13 [Section titled “1.9.0-rc.41 - 2026-06-13”](#190-rc41---2026-06-13) ### Fixed [Section titled “Fixed”](#fixed-24) * **JNI codegen: `&[&str]` core params no longer fail E0308.** The JNI function/method shims emitted `&names` for `Vec` slots, which coerces to `&[String]` but not `&[&str]`. Core fns declared as `&[&str]` (e.g. `download(&[&str])`) failed to compile with `expected reference &[&str], found reference &Vec`. Alef now consults the IR `vec_inner_is_ref` flag to materialise a `Vec<&str>` and borrow it (`&names.iter().map(|s| s.as_str()).collect::>()`) when the core function expects `&[&str]`, matching the existing Dart codegen behaviour. Folded into the alef 0.24.17 release. ## 1.9.0-rc.40 - 2026-06-13 [Section titled “1.9.0-rc.40 - 2026-06-13”](#190-rc40---2026-06-13) ### Fixed [Section titled “Fixed”](#fixed-25) * **Removed stray `test_apps/kotlin_android/file:/tmp/` directory that broke every Windows publish job.** A prior regen wrote a runtime download cache (`.download.lock`, `manifest.json`) into a literal directory named `file:` because a `cache_dir` value of the form `file:/tmp/…` was interpreted as a relative path rather than a URI. The `:` is illegal in Windows paths, so every `actions/checkout` step on Windows failed with `invalid path 'test_apps/kotlin_android/file:/tmp/.download.lock'` — collapsing 21 Windows builds in the rc.39 publish run and leaving npm / PyPI / NuGet / Maven stuck at rc.38. The bad files are removed and `.gitignore` now blocks the pattern (`test_apps/*/file:/`) alongside the existing `test_documents/file:/` guard. ## 1.9.0-rc.39 - 2026-06-12 [Section titled “1.9.0-rc.39 - 2026-06-12”](#190-rc39---2026-06-12) ### Added [Section titled “Added”](#added-5) * **Hierarchical data extraction for 17 data-format languages (#136).** Set `data_extraction = true` on `ProcessConfig` to extract a nested `DataNode` tree preserving the original document’s hierarchy. Covers JSON, HJSON, JSON5, TOML, properties, Cue, HCL, HOCON, KDL, YAML, INI, EditorConfig, PO, Nginx, Caddy (key-value pairs); XML and DTD (element shape); and CSV/PSV (sequence shape). See [docs/guides/intelligence.md#data-extraction](https://docs.tree-sitter-language-pack.xberg.io/guides/intelligence/#data-extraction). * **JNI is a first-class test-apps target for Kotlin Android host-JVM.** The kotlin\_android test app’s host-JVM gradle tests now satisfy `Language::Jni` in `alef test-apps run`, enabling CI/CD verification without Android emulator. Requires alef 0.24.14+. ### Changed [Section titled “Changed”](#changed-26) * **Alef pin bumped 0.24.10 → 0.24.14.** Pulls in the JNI run-default split (host-JVM gradle runner replaces the `Ffi | Jni` no-op), JNI return marshalling for raw `String` / `Option` returns (no more JSON-encoded `"\"python\""` surfacing in Kotlin), Kotlin test emitter `loadLibrary` respecting `[crates.ffi] prefix` (resolves `ts_pack_jni` instead of the literal crate name), and the Kotlin assertion emitter switching list-`contains` checks to a case-insensitive `toString().lowercase().contains(...)` shape that mirrors the Java emitter. ## 1.9.0-rc.32 - 2026-06-11 [Section titled “1.9.0-rc.32 - 2026-06-11”](#190-rc32---2026-06-11) ### Fixed [Section titled “Fixed”](#fixed-26) * **`release-finalize` job guards `Finalize release` on `prepare` success.** The job ran with `if: always()` and unconditionally invoked `finalize-release@v1`, which errors with `INPUT_TAG is required` whenever `prepare`’s `tag` output is empty (cancelled or failed `prepare`). Result: a cancelled rc.31 surfaced as a confusing `Finalize release: failure` on top of the actual upstream cancellation. Now `if: needs.prepare.result == 'success'`. rc.31 publish run 27214336783. * **PHP `test_apps/install.sh` verifies extension load via `extension_loaded()` rather than parsing `php -m` output.** When the PIE-installed extension was already loaded through the global `php.ini`, an explicit `php -d extension=...` invocation caused PHP to emit `Module already loaded` to stderr; the harness’s combined-output capture treated the warning as fatal and the install step exited non-zero before the actual smoke test ran. Switched to `php -r 'exit(extension_loaded("...") ? 0 : 1);'` so the check is decoupled from PHP’s logging and tolerant of double-loading. * **`ts-pack-core-ffi` regen emits zero rustdoc warnings.** Previously the regen produced 26 broken-intra-doc-link warnings on every build because emitted `///` comments contained bare and backtick-wrapped intra-doc-link forms (`[download()]`, ``[`Error::LanguageNotFound`]``, etc.) referencing core-crate items not in scope from the FFI wrapper. Pulled in via the alef 0.24.2 bump. * **`ts-pack-core-node` regen emits zero rustdoc warnings.** The previous regen left `Vec` and `Array` bare in `JsBytes` doc comments, which rustdoc parsed as unclosed HTML tags. Pulled in via the alef 0.24.2 bump. * **`test_apps/zig/build.zig.zon` URLs now match publish-zig asset naming.** Previous releases emitted URLs with Go-style platform labels (`linux-aarch64`, `macos-arm64`, …) while published assets used Rust target triples (`aarch64-unknown-linux-gnu`, `aarch64-apple-darwin`, …), so `zig fetch` 404’d. The alef 0.24.2 bump switches both sides to Rust triples; tslp’s `alef.toml` `[crates.e2e.registry.packages.zig.platform_hashes]` keys updated to match. Reverts the simple-arch direction taken in rc.31. ### Changed [Section titled “Changed”](#changed-27) * **Alef pin bumped 0.23.68 → 0.24.2.** Pulls in the FFI/NAPI rustdoc-warning fixes and Zig URL alignment above, plus a Kotlin Android host JNI artifact for JVM test\_apps (`buildHostJni` / `copyHostJni` Gradle tasks guarded by `alef.skipHostJni`), Go scaffold `module_major` parameterization that lets non-kreuzberg consumers configure their `packages/go/v{N}` layout, and a broad sweep of trait-bridge adapter fixes across Kotlin Android, C#, Java, Node, R, Swift, Dart, Elixir, and Go. * **`crates/ts-pack-core/build.rs` added to the `rust-max-lines` exclude list (1081 LOC > 1000-line ceiling).** Joins the existing remediation backlog of large files awaiting split. ## 1.9.0-rc.31 - 2026-06-09 [Section titled “1.9.0-rc.31 - 2026-06-09”](#190-rc31---2026-06-09) ### Fixed [Section titled “Fixed”](#fixed-27) * **Alef pin bumped 0.23.58 → 0.23.65.** Pulls in two test\_apps-driven fixes from alef 0.23.65: * **kotlin-android**: Foojay toolchain resolver plugin bumped v0.7.0 → v0.10.0 in both `settings.gradle.kts` emitters. v0.7.0 referenced `JvmVendorSpec.IBM_SEMERU`, which Gradle 9.0+ removed (renamed to `IBM`); Gradle 9.5.1 hosts failed at project-evaluation with `Class org.gradle.jvm.toolchain.JvmVendorSpec does not have member field 'IBM_SEMERU'`. v0.10.0 is Gradle 9.x-safe. * **zig**: published tarballs now use simple-arch platform labels (`linux-x86_64`, `linux-aarch64`, `macos-arm64`, `macos-x86_64`, `windows-x86_64`) matching `build.zig.zon` URL templates. Previously `RustTarget::platform_for(Language::Zig)` returned the rust triple, so `alef publish package --lang zig --target …` emitted `…-aarch64-apple-darwin.tar.gz` but the e2e codegen’s URL templates and per-platform `[crates.e2e.registry.packages.zig.platform_hashes]` user config used the simple-arch convention. Consumers’ `zig fetch` then 404’d. ## 1.9.0-rc.30 - 2026-06-09 [Section titled “1.9.0-rc.30 - 2026-06-09”](#190-rc30---2026-06-09) ### Fixed [Section titled “Fixed”](#fixed-28) * **`Stage Go FFI libraries` step uses `git add -f`.** Root `.gitignore` globally ignores `*.so`/`*.dylib`/`*.dll`/`*.lib`, so the plain `git add` silently refused to stage the downloaded FFI artifacts under `packages/go/.lib/`. `xargs` propagated the (silent) failure as exit 123, failing the step before the `packages/go/v` subtree tag could be pushed. Added `-f` so the published Go module deliberately ships pre-built FFI artifacts past the global ignore. Fixes rc.29 publish run 27192809836 Stage Go FFI failure. * **`upload-release-assets@v1` receives the publisher-app token as an action input on all 4 cross-repo-write call sites.** The shared action sets `GH_TOKEN` inside its own composite step from `inputs.token` (default `github.token`), so a step-level `env: GH_TOKEN: …` on the calling job had no effect — uploads ran with the read-only default `GITHUB_TOKEN` and hit `HTTP 403: Resource not accessible by integration`. Now passes `token: ${{ steps.app-token.outputs.token }}` on the Go FFI, Elixir NIF, Swift bundle, and Zig upload sites. The PHP PIE upload site (line 2473) keeps the default token because its job declares `permissions: contents: write`. Fixes rc.29 publish run 27192809836 Upload Go FFI 403. * **Pulls in `xberg-io/actions` v1.8.49 retry-on-SSL upload fix.** `publish-github-release/scripts/upload_artifacts.py` now retries 5× with exponential backoff on `URLError` / `ssl.SSLError` / `ConnectionError` / `TimeoutError` / HTTP 5xx. rc.29 parser-sources bundle upload hit a transient `ssl.SSLEOFError` mid-upload on a 30 MB asset and cascaded to \~15 dependent failures (skipping `publish-crates`, which broke every PHP/Ruby/Elixir/Python-sdist `cargo generate-lockfile` against the unpublished workspace member); the retry absorbs the SSL race. ## 1.9.0-rc.29 - 2026-06-09 [Section titled “1.9.0-rc.29 - 2026-06-09”](#190-rc29---2026-06-09) ### Changed [Section titled “Changed”](#changed-28) * **Alef pin bumped 0.23.48 → 0.23.58.** Pulls in the PHP MINIT module-startup mutex (0.23.50 — `crates/ts-pack-core-php/src/lib.rs` now wires `__ext_php_rs_module_startup` into the extension builder so class registrations actually reach PHP), the NAPI TS overload/optional-param signature cleanup (0.23.55), the NAPI arrow-type return type strip fix (0.23.54), the napi service-wrapper lowerCamelCase fix (0.23.57), per-item version annotations in the IR + docs generator (0.23.58), the NAPI enum variant JSDoc `*/` escape (0.23.58 — `crates/ts-pack-core-node/index.d.ts` no longer prematurely closes the JSDoc block around `DocstringFormat::JSDoc` / `::JavaDoc` variant docs), and a sweep of Java/Kotlin/Zig/Dart formatting normalization across all generated binding files. * **Release automation migrated to the `kreuzberg-dev-publisher` GitHub App.** All 15 release-write jobs in `.github/workflows/publish.yaml` (parser-sources upload, parser-binaries upload, Go FFI upload, C FFI upload, Elixir NIF upload + draft create, Hex checksums fetch, pubdev workflow dispatch, Swift manifest commit + tag force-push, Zig upload, CLI upload, homebrew formula render + tap push, homebrew bottle build + DSL merge + tap push, Go subtree commit + tag push, finalize-release) now mint a short-lived installation token via `actions/create-github-app-token@v2` keyed off the org secrets `BOT_APP_ID` / `BOT_APP_PRIVATE_KEY`. Bot identity: `kreuzberg-dev-publisher[bot]` (user id 291994444). Eliminates the `HOMEBREW_TOKEN` PAT for cross-repo tap pushes and lets tag pushes trigger downstream workflows (`GITHUB_TOKEN`-driven pushes don’t). Branch protection on `main` requires `kreuzberg-dev-publisher[bot]` in the bypass list. ### Fixed [Section titled “Fixed”](#fixed-29) * **`Stage Go FFI libraries` step in `.github/workflows/publish.yaml` now resolves the artifact path correctly.** The step `cd`s into `packages/go/` before walking the downloaded artifact tree, so the `find` invocation needs `../../tmp/go-ffi-all` (two levels up to the repo root). Commit `1de6c8dca` introduced `../../../tmp/go-ffi-all` (three levels up), pointing one directory above the workspace root → `find: '…/tmp/go-ffi-all': No such file or directory` → exit 1 → `packages/go/v1.9.0-rc.28` subtree tag never pushed. Manually staged + tagged rc.28; the next publish run picks up the fix. ## 1.9.0-rc.28 - 2026-06-08 [Section titled “1.9.0-rc.28 - 2026-06-08”](#190-rc28---2026-06-08) ### Fixed [Section titled “Fixed”](#fixed-30) * **Homebrew `libts-pack` bottle now ships with all 306 grammars statically compiled.** The `build-c-ffi` step in `.github/workflows/publish.yaml` was invoking `alef publish build --lang ffi` without `TSLP_LANGUAGES`, so `crates/ts-pack-core/build.rs` defaulted to zero statically-compiled grammars and the resulting FFI tarball (downloaded verbatim by the libts-pack formula) had an empty language registry. The bottle’s `ts_pack_available_languages()` returned an empty string, breaking `test_apps/homebrew/ffi_smoke.c`. Step now sets `TSLP_LANGUAGES` to the full language list (via the same `python3 -c "import json"` extraction used by the CLI build) and `TSLP_LINK_MODE=static`. * **C# NuGet `TreeSitterLanguagePack` package now bundles an FFI dylib with all 306 grammars statically compiled.** Same root cause as the libts-pack fix above — the `build-csharp-native` step invoked `build-csharp-natives@v1` without setting `TSLP_LANGUAGES`. The composite action’s native cargo build inherits the calling step’s env, so adding `TSLP_LANGUAGES`/`TSLP_LINK_MODE=static`/`PROJECT_ROOT` on the step propagates into cargo. Fixes the `Language 'comment' not found` failure surfaced by `test_apps/csharp` against rc.27. * **`CommentKind::Block` and `CommentKind::Doc` rustdoc no longer contains literal `*/` inside backticks.** The `*/` sequence inside `` `/* ... */` `` code spans was landing verbatim in NAPI-RS-emitted JSDoc, prematurely closing the `/** ... */` block and triggering oxlint `TS(1164): Computed property names are not allowed in enums`. Reworded the rustdoc to avoid the `*/` terminator. (Alef 0.23.47 added an `escape_jsdoc_block_close` sanitization helper but it does not reach the napi enum variant doc path — tracked as alef 0.23.48+ follow-up.) ### Changed [Section titled “Changed”](#changed-29) * **Alef pin bumped 0.23.34 → 0.23.48.** Pulls in the Zig null-check primitive-return fix (0.23.47), PHP module entry explicit-name fix (0.23.47), JSDoc `*/` sanitization helper (0.23.47), kotlin-android foojay-resolver plugin emission (0.23.47), Zig publish package name using Zig platform mapping (0.23.48), Zig null-guard returning canonical `error.Serialization` (0.23.47), FFI Finalize owner-pointer preservation (0.23.46), and the c download\_ffi.sh asset name + zig cache clear + php pie always-install fixes (0.23.43–45). ## 1.9.0-rc.27 - 2026-06-08 [Section titled “1.9.0-rc.27 - 2026-06-08”](#190-rc27---2026-06-08) ### Fixed [Section titled “Fixed”](#fixed-31) * **Publish smoke install: scope `--no-binary` to `tree-sitter-language-pack`.** `pip install --no-binary :all: --no-build-isolation` forced source builds for transitive deps too and pip then failed `BackendUnavailable: Cannot import 'hatchling.build'` because the smoke venv only pre-installed maturin + setuptools + wheel. The smoke step now scopes `--no-binary` to just our package; transitives use their published wheels. * **Exclude `php8.5 / macos-arm64` from the PIE matrix.** `shivammathur/setup-php@2.37.1` cannot install PHP 8.5 on macOS arm64 — the brew arm64 bottle is not yet published, and the macOS arm64 runner images ship no pre-installed PHP. All other PHP 8.5 variants build cleanly. Re-enable when upstream catches up. * **Retry transient HTTP errors when downloading parser sources in `crates/ts-pack-core/build.rs`.** `fetch_bytes` now retries up to 6 times with exponential backoff (2s → 64s) on any ureq error, covering both network blips and the GitHub release CDN’s intermittent 504s. Without retries, a single 504 mid-`cargo publish` verify-build would blow up the publish workflow (as happened on rc.26’s `Publish Rust crates` job during the 2026-06-08 GH CDN incident). * **Local-clone fallback in `crates/ts-pack-core/build.rs`.** When the workspace `parsers/` tree is empty (gitignored on a fresh clone) and the GH release tarball for `parser-sources-{version}.tar.zst` isn’t published yet (rc builds during the publish workflow window), the build no longer panics on a 404. The new resolution order is: workspace populated → OUT\_DIR cache → `scripts/clone_vendors.py` (if present, dev workspace) → GH release tarball. The local-clone path tries `uv run --no-sync`, `uv run`, `python3`, and `python` in turn so it works across dev environments. Existing `TSLP_OFFLINE` and `TSLP_SOURCE_BUNDLE_URL` overrides are unchanged. ### Added [Section titled “Added”](#added-6) * **`get_tags_query(language: &str) -> Option<&'static str>`** — new public accessor in `crates/ts-pack-core` mirroring `get_highlights_query` / `get_injections_query` / `get_locals_query`. Returns `Some` for the 15 languages with vendored `tags.scm` (rust, kotlin, csharp, swift, gleam, gap, al, enforce, gdshader, roc, cfml, ql, tact, sourcepawn, mojo) and `None` otherwise. Propagated to the PyO3, NAPI, and FFI bindings via the alef codegen cascade. * **`gherkin` grammar.** Pre-compiled `tree-sitter-gherkin` parser for `.feature` files. Source: `SamyAB/tree-sitter-gherkin` pinned at `43873ee8de16476635b48d52c46f5b6407cb5c09`. ### Fixed [Section titled “Fixed”](#fixed-32) * **Bump alef pin `0.23.30 → 0.23.34` and regen all bindings, e2e, test\_apps.** Pulls in 7 rolling alef fixes triaged from rc.25 test\_app failures: php `#[php_class]` constants escape PHP-reserved variant names (`CLASS_`/`INTERFACE_`/…) avoiding `Fatal error: A class constant must not be called 'class'`; java javadoc `escape_javadoc_line` rewrites nested `*/` inside `{@code …}` to `*/` so the surrounding `/** … */` block isn’t closed prematurely (was breaking `mvn compile` on `CommentKind.java` + `DocstringFormat.java`); swift `ZSwiftPluginHelpers.swift` imports `RustBridge` (not `RustBridgeC`) so `RustString` resolves; zig test\_apps\_run sed pattern `s/}, */}\n/g` correctly splits `build.zig.zon` dep blocks so `zig fetch --save` populates `.hash` fields; dart flutter\_rust\_bridge external library loader uses `Abi.current()` instead of `Platform.version` string parsing for reliable arch detection; java e2e pom.xml antrun copy-native-lib step falls back from `ffi/lib/` (pre-built FFI tarball) to `target/release/` (local Cargo build); php install.sh appends `extension=` to the loaded php.ini after PIE 1.4.5+ install (PIE’s `--skip-enable-extension` default no longer auto-enables). (`alef.toml`, 482-file regen across `packages/`, `e2e/`, `crates/`, `test_apps/`) ### Fixed [Section titled “Fixed”](#fixed-33) * **Omit field-level javadoc in multiline Java record declarations for PMD compliance.** PMD 7.x does not recognize javadoc preceding annotations as belonging to record components (DanglingJavadoc rule). Field-level documentation is omitted from multiline record declarations since records are self-documenting value types and class-level record javadoc provides sufficient context. (Alef upstream: `src/backends/java/gen_bindings/types.rs`) * **Suppress `missing_docs` lint in generated swift-bridge bindings.** The swift-bridge crate (`packages/swift/rust/src/lib.rs`) is entirely generated code with 1:1 wrapper mirrors of `tree_sitter_language_pack` types. Rustdoc coverage on these wrappers is not meaningful — the file now emits `#![allow(missing_docs)]` at the crate root, matching the pyo3 and wasm backends. (Alef upstream: `src/backends/swift/gen_rust_crate/mod.rs`) * **Bump alef pin `0.20.10 → 0.20.12` and regen all bindings, e2e, docs, test\_apps, README.** Pulls in upstream alef fixes since the rc.16 regen: `v0.20.11` ruby `Dir.chdir(ext//native)` wrap on `RbSys::ExtensionTask.new` so `Cargo::Metadata` lookup finds the workspace-excluded crate; go `embed`-import-named-not-blank + extra-blank-line cleanup; R extendr unit-enum constructor wrappers. `v0.20.12` R extendr numeric-double handling + fixture-extracted backend name; PHP e2e static-method teardown; ruby restore `config.ext_dir = "native"` in extconf.rb so build-time mkmf path matches the new `ExtensionTask` resolution. Subsequent main fixes consumed via local hand-edit pending alef 0.20.13: rustler `RustlerPrecompiled` `base_url:` template pre-wrap so `mix format` is idempotent (`packages/elixir/lib/tree_sitter_language_pack/native.ex` — wrapped manually until the alef `300d0b85b` rustler-template fix ships). (`alef.toml`, 435+ regen files across `packages/`, `e2e/`, `crates/ts-pack-core-*`, `docs/reference/`, `test_apps/`, `README.md`) * **Drop `alef fmt` from `Check version sync` step in both CI workflows.** The rc.16 hotfix wired `alef fmt` between `alef sync-versions` and the diff check to absorb `index.js` oxfmt drift. But `alef fmt` invokes every post-gen formatter at once (clang-format, ktlint, php-cs-fixer, dotnet format, mvn spotless, swift-format, mix format, …) — CI doesn’t install most of those (PHP `vendor/bin/php-cs-fixer` missing, clang-format pipeline empties to stdin), so the step fails with `[ffi] error: cannot use -i when reading from stdin` and `[php] Could not open input file`. Revert: only `alef sync-versions` runs; `alef 0.20.12` no longer drifts `index.js` post-sync so the original `-w --ignore-blank-lines` diff check passes idempotently. (`.github/workflows/{ci,ci-validate}.yaml`) * **CI Validate: unblock rc.16 by pinning `pyproject-fmt==2.5.0`, applying `alef fmt` after `alef sync-versions`, and refreshing two version-pin manifests the rc.15→rc.16 regen missed.** Three independent CI failures on HEAD `447a5f78`: (1) the `pyproject-fmt` prek hook crashes in argparse (`add_argument("--table-format", help="...")`) under newer pyproject-fmt releases — pinned to `2.5.0` via `additional_dependencies` so prek installs the last working version without forking `xberg-io/pre-commit-hooks`; (2) the `Check version sync` step in `.github/workflows/{ci,ci-validate}.yaml` ran `alef sync-versions` and then failed `git diff -w` on `crates/ts-pack-core-node/index.js` where alef emits 2-space wrapped output that diverges from the oxfmt-formatted committed file — added `alef fmt` between sync and diff so the post-gen formatters bring output back to the committed shape; (3) `e2e/go/go.mod` still declared `v0.0.0` and `test_apps/swift/Package.swift` still declared `from: "1.8.1"`, which `alef sync-versions` on CI 0.20.10 would rewrite — hand-bumped both to `1.9.0-rc.16` so the diff check passes idempotently. (`.pre-commit-config.yaml`, `.github/workflows/ci-validate.yaml`, `.github/workflows/ci.yaml`, `e2e/go/go.mod`, `test_apps/swift/Package.swift`) * **CI Validate: refresh pnpm `minimumReleaseAgeExclude` allowlist for rc.16 platform packages and pick up new `linux-*-musl` variants.** `CI Validate / Lint & Format` and `CI / Validate (Lint & Format)` were failing with `[ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION]` against the six `@kreuzberg/tree-sitter-language-pack-*@1.9.0-rc.16` platform packages (published 2026-05-29T05:51Z, within the 24h supply-chain age cutoff). Bumped the six existing allowlist entries from `rc.11 → rc.16` and added two new entries for `linux-x64-musl` / `linux-arm64-musl`, which the alef 0.20.10 regen now declares as `optionalDependencies` of `crates/ts-pack-core-node/package.json`. Regenerated `pnpm-lock.yaml` (`pnpm install --lockfile-only`) so the eight platform entries match the manifest and `pnpm install --frozen-lockfile` succeeds in both the node and wasm workspaces. (`pnpm-workspace.yaml`, `pnpm-lock.yaml`) * **Restore typed `DownloadError` for Python (and equivalent typed exceptions across other bindings).** Issue #133: `DownloadError` was dropped during the alef polyglot migration (commit `8557c150`) because the `Download`, `ChecksumMismatch`, and `CacheLock` variants on `crates/ts-pack-core/src/error.rs::Error` were `#[cfg(feature = "download")]`-gated, and the alef variant extractor skipped cfg-gated variants when generating the public exception taxonomy. `get_parser("not_a_real_language")` consequently raised a bare `RuntimeError` carrying the message `"Download error: ..."` instead of a catchable typed exception. The three variants are pure string carriers with no extra dependencies, so the cfg gates were unnecessary — they now live unconditionally on the `Error` enum. The next alef regen extracts them as `DownloadError`, `ChecksumMismatchError`, and `CacheLockError` (Python) and equivalents in every other binding, restoring the documented `except DownloadError` catch path. The `Json` and `Toml` variants remain feature-gated because they carry external dependency types. (`crates/ts-pack-core/src/error.rs`) ### Changed [Section titled “Changed”](#changed-30) * **Docs and READMEs bumped to 306 grammars after the gherkin addition.** Updated hand-written count references in `crates/ts-pack-core/{README.md,src/lib.rs}`, `docs/reference/api-*.md` (15 files), `skills/tree-sitter-language-pack/{SKILL.md,references/*.md}`, `.ai-rulez/domains/parser-compilation/context/tree-sitter-overview.md`, and the OOM-mitigation comments in `.github/workflows/publish.yaml`. Remaining `305` mentions in alef-generated package metadata (`packages/*/Cargo.toml`, `composer.json`, `pyproject.toml`, etc.) refresh on next `task alef:generate`; the `alef.toml` source-of-truth is already at 306. * **repo**: Add `.gitattributes` marking all alef-generated output directories (`packages/**`, `crates/*-{py,php,ffi,node,wasm}/**`, `e2e/**`) as `linguist-generated=true` so generated files collapse in GitHub PR diffs. * **Bump alef to 0.18.0 and regen all bindings, e2e, docs.** Major upstream restructure: workspace renamed `alef-cli` → `alef` (single distributable crate; 28 internal `alef-*` member crates yanked), Node/WASM crate directories renamed (`ts-pack-core-node`, `ts-pack-core-wasm`), and zig/c FFI search paths reorganised. Configuration follow-ups in this repo: `[crates.{node,wasm}.crate_dir]` overrides pin the napi/wasm-pack build to the renamed crate dirs; `napi build --platform --release` produces per-platform `.node` artifacts (fixes “Cannot find module ‘./ts-pack-core-node.darwin-arm64.node’” on Node e2e); zig defaults in `packages/zig/build.zig` switched to `../../target/release` + `../../crates/ts-pack-core-ffi/include`, with `.task/zig.yml` and the `[crates.test.zig]` alef e2e step both passing `-Dffi_path=../../target/release`; C e2e command corrected from `./test_runner` → `./run_tests` and `.task/c.yml` switched from `--lang ffi` → `--lang c`; new `[crates.e2e].result_fields` array + `[crates.e2e.fields_c_types]` map drive alef’s namespace-aware field navigation for the C `process_result.metrics → FileMetrics → uintptr_t` accessors. Upstream alef fix in 0.18.0: `namespace_stripped_path` no longer strips path segments when `result_fields` is empty, so legacy bindings (no `result_fields` configured) keep dotted-field paths intact. All 14 language e2e suites pass after regen. * **Source-gem publish now uses the shared `rewrite-native-deps@v1` action.** The `publish-rubygems` job’s source-gem fallback rewrites the native ext’s workspace path-dependency (`packages/ruby/ext/ts_pack_core_rb/native/Cargo.toml` → `crates/ts-pack-core`) to a registry version-dependency so the shipped manifest resolves on user install. Replaced the dead “Set up Python (for vendor script)” + “Vendor core for source gem” steps with `xberg-io/actions/rewrite-native-deps@v1` (`lang: ruby`) before `gem build`, matching the precompiled `build-ruby-gem` job. (`.github/workflows/publish.yaml`) ### Removed [Section titled “Removed”](#removed-2) * **`wolfram` grammar dropped from the language pack.** `tree-sitter-wolfram` produces glibc heap corruption (`free(): invalid next size`) when parsing trivial input under serial test execution on Linux; macOS allocator silently tolerated the corruption. The entire upstream ecosystem is unmaintained (canonical `bostick/tree-sitter-wolfram` last touched 2021-11-11 with 3 stars; every known fork — `LumaKernel`, `LoganAMorrison`, `JuanG970`, `jakassebaum` — ships the same `LANGUAGE_VERSION 13` parser tables and is inactive). Rather than fork-and-maintain a Wolfram grammar in-house for marginal demand, the entry is removed from `language_definitions.json`, all CI `TSLP_LANGUAGES` lists, the smoke fixture, the e2e harness, the docs, and the README ecosystem listings. **Total supported grammar count drops from 306 to 305**, which matches the long-standing “305 languages” marketing copy (previously off-by-one due to the broken wolfram entry). * **Dead workspace-vendor scripts superseded by shared GitHub Actions.** Deleted `scripts/ci/php/vendor-core.py` (rewrote the `exclude`d `crates/ts-pack-php` crate; publish uses the `crates/ts-pack-core-php` crate via `build-php-extension@v1`) and `scripts/ci/ruby/vendor-core.py` (targeted the nonexistent `crates/ts-pack-ruby` crate; no-op). Dropped the now-dangling `vendor` tasks from `.task/php.yml` and `.task/ruby.yml`; the local PHP `build`/`build:dev` tasks now build the `ts-pack-core-php` crate directly, mirroring CI. (`scripts/ci/php/vendor-core.py`, `scripts/ci/ruby/vendor-core.py`, `.task/php.yml`, `.task/ruby.yml`) ## 1.9.0-rc.1 - 2026-05-22 [Section titled “1.9.0-rc.1 - 2026-05-22”](#190-rc1---2026-05-22) ### Added [Section titled “Added”](#added-7) * Four new language bindings via alef 0.16.6, taking total binding count from 10 to 14: * **Dart / Flutter** — `dart pub add tree_sitter_language_pack`. Built with flutter\_rust\_bridge for isolate-safe Future APIs. * **Kotlin (Android)** — `dev.kreuzberg.tslp:tslp-android` AAR on Maven Central. JNI-based with per-ABI native libraries (arm64-v8a, armeabi-v7a, x86\_64, x86). JVM Kotlin users continue to consume the canonical Java / Panama-FFM package. * **Swift** — `TreeSitterLanguagePack` via SwiftPM. swift-bridge for macOS, iOS, and Linux. * **Zig** — `zig fetch --save ` from GitHub Releases. Direct C FFI via `@cImport`. * Two new Rust binding crates: `tree-sitter-language-pack-dart` (FRB bridge) and `tree-sitter-language-pack-swift` (swift-bridge). * Hand-written `crates/ts-pack-core-jni` Rust crate exporting `Java_...` JNI symbols for the Kotlin-Android binding (excluded from the default workspace build because it cross-compiles via `cargo ndk`). * Per-language CI workflows: `ci-zig.yaml`, `ci-swift.yaml`, `ci-dart.yaml`, plus a combined `ci-mobile.yaml` covering Android cross-compile + iOS cargo check. * Publish jobs for pub.dev (`publish-pub`), Swift Package Index (`publish-swift`), Zig (`publish-zig` → GitHub Release tarball), and Maven Central kotlin-android (`publish-kotlin-android`). ### Fixed [Section titled “Fixed”](#fixed-34) * **Download cache is now safe under concurrent multi-process access.** `DOWNLOAD_CACHE_LOCK` in `crates/ts-pack-core/src/lib.rs` was a `Mutex<()>` — intra-process only — so multi-worker servers (gunicorn / Puma / Node cluster), fan-out build pipelines (`make -j8`, parallel test runners), and the zig e2e suite (`zig build test` spawns eight test binaries in parallel) all raced on the same `~/.cache/tree-sitter-language-pack/v{version}/` directory. Partial `entry.unpack` writes were observable to other workers’ `libloading::open`, producing intermittent `LanguageNotFound` / segfaults on first request for an uncached language; N processes could also each redundantly pull the 50MB platform bundle. Cache writes are now atomic (write to `/..tmp..` then `fs::rename` — readers see old, new, or nothing, never partial) and the bundle-fetch / extract / clean critical section is serialized across processes with an exclusive `fd-lock` on `/.download.lock`. Double-checked locking preserves the lock-free hot path: steady-state `is_cached` lookups never pay the OS file-lock cost. New `Error::CacheLock(String)` variant surfaces lock-acquisition failures cleanly. Affects every binding (Python, Node.js, Ruby, PHP, Go, Java, C#, Elixir, WASM, Dart, Swift, Zig, Kotlin-Android) because the fix lives entirely in the shared `ts-pack-core` Rust crate. New `fd-lock = "4"` dependency (gated under the `download` feature). Cross-process safety relies on `flock` semantics, which are unreliable on NFS — users with `XDG_CACHE_HOME` on NFS should use a local-FS cache or serialize at the application layer. (`crates/ts-pack-core/src/{download.rs,error.rs}`, `crates/ts-pack-core/Cargo.toml`, `Cargo.toml`, new `crates/ts-pack-core/tests/concurrent_download.rs`) * **Zig e2e auto-omits fixtures outside the static-compiled grammar set (regen on alef `65f1a129`).** Declared `[crates.zig].languages = []` mirroring the `TSLP_LANGUAGES` value in `[crates.test.zig].before`. Alef’s new Zig codegen filter consults both `input.language` and `input.config.language` and drops fixtures whose target grammar is not in the list (mirroring the WASM `f9e0ff50` pattern). Eliminates `smoke_bibtex` and every other non-static-set test that previously failed at parser-load time. Also reverts the per-fixture `skip: { languages: ["zig"] }` workaround on `fixtures/smoke/actionscript.json` since the auto-omit subsumes it. (`alef.toml`, `fixtures/smoke/actionscript.json`) * **swift e2e: `process` `contains` assertions on `Vec` fields aggregate every stringy accessor (regen on alef `857c55d1`).** `testProcessPythonImportsDetail` and `testProcessRustStructureName` previously failed because the codegen relied on `result_field_accessor` naming a single “primary” accessor per array field (`imports → source`, `structure → kind`), which misses values surfaced on sibling fields — `"os"` against `ImportInfo.items`, `"MyConfig"` against `StructureItem.name` rather than `StructureKind`. The regenerated tests now emit a `contains(where: { item in … })` closure that gathers every text-bearing accessor (String, Option, Vec, serde-enum) into a `[String]` and substring-matches the expected value, mirroring python’s `_alef_e2e_item_texts`. Swift e2e: 411 tests, 0 failures. (`e2e/swift_e2e/Tests/TreeSitterLanguagePackE2ETests/ProcessTests.swift`) * **Maven JAR native layout collapses every classifier under `natives/native/` ([#128](https://github.com/xberg-io/tree-sitter-language-pack/issues/128)).** The re-stage loop in `build-maven-package` walked one `dirname` too far when extracting the classifier from each lib’s path, so all six platform libs landed at `natives/native/{lib}` instead of `natives/{classifier}/{lib}`. The Maven Central JAR shipped in v1.8.1 contained only three files (one per `.so`/`.dylib`/`.dll` extension) and `TreeSitterLanguagePack.getParser("…")` failed with `UnsatisfiedLinkError: Expected resource: /natives/windows-x86_64/ts_pack_core_ffi.dll`. Fixed the path-walk depth, and hardened both build-side and deploy-side verification steps to require every `linux-x86_64 / linux-arm64 / macos-arm64 / macos-x86_64 / windows-x86_64 / windows-arm64` classifier directory is present in the staged JAR so the regression cannot ship again. Additionally corrected the Windows-ARM classifier from `windows-aarch64` to `windows-arm64`: the Java loader (`NativeLib.resolveNativesRid`) normalizes every ARM architecture to `arm64` and resolves to `natives/windows-arm64/`, so a JAR staged under `windows-aarch64` would still `UnsatisfiedLinkError` on Windows ARM64 — the publish matrix and both verification steps now use `windows-arm64`, consistent with the `linux-arm64` / `macos-arm64` classifiers and the loader. (`.github/workflows/publish.yaml`) * **WASM e2e local-feasibility + auto-skip wiring.** `[crates.test.wasm].before` previously ran `wasm-pack build` with no `TSLP_LANGUAGES` set, which triggered a full 305-grammar static build — the 97MB `abl/parser.c` alone hangs clang at -O2 for tens of minutes. Mirrored the publish-wasm CI environment locally: `TSLP_LINK_MODE=static TSLP_LANGUAGES= CARGO_PROFILE_RELEASE_LTO=false CARGO_PROFILE_RELEASE_CODEGEN_UNITS=16`. Also declared `[crates.wasm].languages = []` so alef’s wasm e2e auto-skip path correctly elides 268 of the 302 smoke tests for grammars not in the bundle (with the matching alef `f23ae5d3` / `f9e0ff50` fixes that teach the wasm filter to look up both `input.language` and `input.config.language`). (`alef.toml`) * **Regen on alef HEAD (csharp List, go os import, php deterministic accessor ordering, swift codegen trifecta).** Pulls in upstream alef fixes: `4f6a9056` csharp List emission for `mock_url_list`; `06caa440` go `os` import include guard for `mock_url_list`; `1fde7aae` PHP deterministic accessor extraction order (HashMap→BTreeMap; resolves the recurring `$imports`/`$structure` flip in `e2e/php/tests/ProcessTest.php`); `13717e24` swift e2e — trailing `()` on scalar accessors that bridge through opaque structs, drop spurious `?.map ... ?? []` on non-optional `RustVec` accessors, and camelCase swift-bridge method names (e.g. `asStr()` not `as_str()`); plus the wasm `input.config.language` filter follow-up cited above. (`e2e/php/**`, `e2e/swift_e2e/**`, `e2e/wasm/**`, `e2e/zig/**`) * **npm darwin-x64 NAPI binary missing ([#127](https://github.com/xberg-io/tree-sitter-language-pack/issues/127)).** `crates/ts-pack-core-node/package.json#napi.targets` already listed `x86_64-apple-darwin`, but the `build-node-native` matrix in `.github/workflows/publish.yaml` omitted the `macos-15-intel` runner — so v1.8.0 / v1.8.1 npm tarballs shipped without `ts-pack-core-node.darwin-x64.node`, breaking `require('@kreuzberg/tree-sitter-language-pack')` on Intel Macs. Added a `macos-15-intel` / `darwin-x64` / `x86_64-apple-darwin` row to the matrix, mirroring the parity already present in the Python/Ruby/Java/Go publish matrices. The next published version (≥1.8.2) will include the darwin-x64 binary. (`.github/workflows/publish.yaml`) * **Regen on alef v0.17.13.** Pulls in four upstream fixes since v0.17.11: `fix(alef-e2e/rust): unwrap Option leaf fields in numeric comparison assertions` (the three `greater_than` / `less_than` / `less_than_or_equal` operators no longer fail to compile when the leaf field is `Option`), `fix(alef-e2e/rust): use serde_json::from_str instead of json! macro for fixture json_object args` (sidesteps the macro recursion-limit on fixtures with large JSON payloads), `fix(alef-backend-php): emit Box::default() instead of Box::new(Default::default()) for boxed fallback fields` (resolves `clippy::box-default` -D warnings on the PHP umbrella crate), and `feat(alef-core,alef-e2e/wasm,alef-e2e/typescript): auto-skip wasm fixtures outside the static-compiled language set` (foundational for tslp’s curated wasm32 builds; no-op for now since `[crates.wasm].languages` is empty, but unlocks the future curated-build flow). Side effects in this regen: a few Rust e2e fixture bodies re-formatted, `e2e/c/main.c` cosmetic update, and `packages/swift/rust/Cargo.toml` deps re-ordered. (`alef.toml`, `e2e/{c,php,rust}/**`, `packages/swift/rust/Cargo.toml`) * **CI E2E (.NET) lib-path block uses grouped redirect.** `shellcheck SC2129` flagged four consecutive `echo … >> "$GITHUB_ENV"` lines in the Set library paths for .NET step; consolidated into a single grouped `{ … } >> "$GITHUB_ENV"` block to keep actionlint clean on the workflow. (`.github/workflows/ci-e2e.yaml`) * **Pin alef to v0.17.10.** Bumps `alef_version` in `alef.toml` and the alef pre-commit-hook rev. Lands the Phase-5 leakage-sanitizer chain plus follow-up codegen fixes: v0.17.4 csharp/elixir/kotlin/swift codegen-consumer unblocks; v0.17.5 NAPI/PHP/Java docstring sanitizer wiring; v0.17.7 sanitizer recognises rustdoc test-attribute fences (` ```no_run `, ` ```ignore `, ` ```should_panic `, ` ```compile_fail `, ` ```edition* `) as Rust code (so their bodies are dropped for foreign-language targets); v0.17.8/v0.17.9 csharp U1-bool P/Invoke call-site fix; v0.17.10 Swift free-function forwarder fixes — `Option` returns now use `?.toString()` and host DTO args flow through `.intoRust()` before the bridge call, so `detectLanguageFromExtension/Path/Content`, the `*Query` getters, and `process(_:config:)` compile and execute against the high-level Swift API. Downstream surface: 61 Rust-code-block leaks in `crates/ts-pack-core-node/index.d.ts` and 20+ in `crates/ts-pack-core-php/src/lib.rs` collapse to 0 after this regen. * **Rust e2e `chunks` undefined.** `e2e/rust/tests/process_test.rs` four `test_*_chunking_*` cases were emitting `assert!(chunks.len() >= 2 as usize, ...)` where `chunks` was undeclared (E0425). Same class of bug as the PHP `$chunks` fix; alef’s Rust e2e codegen unconditionally fired the streaming-virtual-field assertion arm for `chunks`/`imports`/`structure` even for non-streaming fixtures. Fix pulled in via alef `a32ca2a0 fix(rust-gen): bind fields_array accessor before len() assertion in e2e tests` — non-streaming fixtures with a colliding `fields_array` field now emit a leading `let {field} = &{result}.{field};` binding. * **`e2e/node` `tree-sitter` dev-dep restored (recurring).** `alef generate` strips `tree-sitter@^0.25.0` from `e2e/node/package.json` on every regen, but `tests/capsule_passthrough.test.ts` imports it to verify FFI capsule type-tag pass-through between our `Language` object and the upstream tree-sitter Node native module. Hand-restored, alongside the corresponding `pnpm-lock.yaml` rows. * **Subsequent regen on top of alef Swift API tightening.** Pulls in alef `2eaa260a fix(swift): hide RustVec/RustString/intoRust from public API; convert at forwarder boundaries` plus a handful of smaller adapter fixes (`fix(alef-backend-pyo3)`, `fix(alef-backend-napi,wasm)`, `fix(alef-backend-ffi)` clippy). Public Swift API surface no longer leaks `RustVec`/`RustString`/`intoRust()`; conversion happens at forwarder boundaries inside generated extensions. * **CI green-up.** Regenerated `pnpm-lock.yaml` to drop the stale `e2e/node → tree-sitter@^0.25.0` devDependency that broke `pnpm install --frozen-lockfile` in `CI Validate`. Regenerated the `docs/reference/api-*.md` set so committed output matches `alef docs` (compact Markdown tables) and `alef verify` stays green on `main`. * **Full alef regen on top of upstream codegen fixes.** Pulls in three alef fixes: `fix(swift): enum intoRust(), Ref→owned init, Vec elem type` (Swift CI was failing on `CommentKind.intoRust()`, `RustStringRef.toString()`, `RustVec` not conforming to `Vectorizable`); `fix(php-gen): bind fields_array accessor before count() assertion in e2e tests` (PHP e2e `test_*_chunking_*` cases were referencing undefined `$chunks`); `fix(alef-backend-go): null-check and box Option returns instead of dereferencing` (generated `packages/go/binding.go` was returning `C.GoString(ptr)` where the signature expected `*string`, breaking `golangci-lint` and `govulncheck`). Side-effect: API docstrings now elide Rust-style `[Type]`-link syntax (e.g. PHP `Node.php` doc comments now read `A single syntax node within a 'Tree'` instead of `A single syntax node within a [`Tree`]`). * **WASM yuck grammar marked unsupported.** `tree-sitter-yuck` produces `RuntimeError: unreachable` when parsing under wasm32 (same class of bug as zig/ziggy, which already skip on wasm). `fixtures/smoke/yuck.json` now carries `skip: { languages: ["wasm"] }`; `alef e2e generate` removed the corresponding test from `e2e/wasm/tests/smoke.test.ts`. Native bindings remain unaffected. * **`package.json` pnpm-field cleanup.** Removed the now-ignored `pnpm.onlyBuiltDependencies` block from the root `package.json`. pnpm 11 reads that setting from `pnpm-workspace.yaml` (which already declares the same allowlist); the duplicate field made pnpm emit a warning on every install. * **Downloader now honours the host OS trust store by default ([#125](https://github.com/xberg-io/tree-sitter-language-pack/issues/125)).** Manifest and bundle downloads from `github.com/xberg-io/tree-sitter-language-pack/releases/...` previously used ureq 3.x’s default rustls agent, which trusts only the bundled Mozilla webpki roots and ignores the platform store. On Linux/WSL2 hosts where GitHub HTTPS traffic is presented with a chain rooted in a locally trusted (corp / private) CA — and where `curl`, `pip`, and `git` all succeed against the same URL via the OS trust store — first-use parser downloads failed with `DownloadError: ... io: invalid peer certificate: UnknownIssuer`. The downloader now constructs a configured `ureq::Agent` with `RootCerts::PlatformVerifier` by default (via `rustls-platform-verifier`), matching the behaviour of every other host-trust-aware HTTP client on the system. Set `TREE_SITTER_LANGUAGE_PACK_TLS_ROOTS=webpki` to opt back into ureq’s bundled Mozilla roots; set `TREE_SITTER_LANGUAGE_PACK_TLS_ROOTS=platform` to make the default explicit. Affects every binding (Python, Node.js, Ruby, PHP, Go, Java, C#, Elixir, WASM, Dart, Swift, Zig, Kotlin-Android) because the fix lives entirely in the shared `ts-pack-core` Rust crate. (`crates/ts-pack-core/src/{download.rs,pack_config.rs}`, workspace `Cargo.toml`) ### Removed [Section titled “Removed”](#removed-3) * **`wolfram` grammar dropped from the language pack.** `tree-sitter-wolfram` produces glibc heap corruption (`free(): invalid next size`) when parsing trivial input under serial test execution on Linux; macOS allocator silently tolerated the corruption. The entire upstream ecosystem is unmaintained (canonical `bostick/tree-sitter-wolfram` last touched 2021-11-11 with 3 stars; every known fork — `LumaKernel`, `LoganAMorrison`, `JuanG970`, `jakassebaum` — ships the same `LANGUAGE_VERSION 13` parser tables and is inactive). Rather than fork-and-maintain a Wolfram grammar in-house for marginal demand, the entry is removed from `language_definitions.json`, all CI `TSLP_LANGUAGES` lists, the smoke fixture, the e2e harness, the docs, and the README ecosystem listings. **Total supported grammar count drops from 306 to 305**, which matches the long-standing “305 languages” marketing copy (previously off-by-one due to the broken wolfram entry). ### Changed [Section titled “Changed”](#changed-31) * **Split pub.dev publish into a dedicated `publish-pubdev.yaml` workflow triggered by `push: tags: v*`.** pub.dev OIDC trusted publishing rejects tokens from `release` events; only `push` and `workflow_dispatch` events are accepted. The new workflow produces an accepted token. One-time setup required: configure pub.dev → tree\_sitter\_language\_pack package → Admin → Automated publishing with workflow path `.github/workflows/publish-pubdev.yaml`. (`.github/workflows/publish-pubdev.yaml`, `.github/workflows/publish.yaml`) * Regenerated all alef-managed surfaces (per-binding READMEs, API reference docs, generated bindings, e2e tests) and the script-managed docs/languages.md + `_supported_languages.py` to reflect the 305-grammar count. * `scripts/generate_grammar_table.py` default output path corrected from `docs/supported-languages.md` to the canonical nav-referenced `docs/languages.md`; Taskfile `docs:generate:languages` `generates:` field updated to match. ## 1.8.1 - 2026-05-13 [Section titled “1.8.1 - 2026-05-13”](#181---2026-05-13) ### Added [Section titled “Added”](#added-8) * E2E fixture coverage for: language alias resolution (`shell→bash`) via `has_language` / `get_language` / `get_parser` (3 fixtures); `download` edge cases — empty list, multiple-language, and unknown-language error path (3 fixtures); error-handling for 120KB sources and `get_language("")` (2 fixtures); and TypeScript function parsing (1 fixture). Brings fixture count from 403 to 412, covering 100% of the public `download`, `get_*`, and `has_language` surface across all 10 language bindings. ### Fixed [Section titled “Fixed”](#fixed-35) * Node: `getLanguage(name)` now returns a real `tree-sitter` `Language` that `new Parser().setLanguage(lang)` accepts at runtime. The previous capsule shim used `napi::bindgen_prelude::External::new` (rejected by `node-tree-sitter`’s `UnwrapLanguage`), wrote the External to `__parser`, and did not type-tag the value. Adopts alef [v0.15.49](https://github.com/xberg-io/alef/releases/tag/v0.15.49) where the napi capsule codegen emits raw `napi_create_external` + `napi_type_tag_object` and reads `property_name`/`type_tag` from `[crates.node.capsule_types]`. * Python: `PackConfig` and `ProcessConfig` type hints now resolve to the `.options` dataclasses, fixing `mypy --strict` errors at every `init(...)` / `process(...)` call site (adopts alef [#72](https://github.com/xberg-io/alef/issues/72)). * Python: restore `SupportedLanguage` as `Literal[...]` of all 306 grammars at `tree_sitter_language_pack.SupportedLanguage`. The symbol was dropped during the alef 0.15.x codegen migration and re-importing it raised `ImportError` in 1.8.0 (#121). * Python: `get_parser("python").parse(b"...")` returns a real `tree_sitter.Tree` again instead of raising `AttributeError`. `get_parser` / `get_language` now return native `tree_sitter.Parser` / `tree_sitter.Language` instances via PyO3 capsule pass-through (alef v0.15.39 wires `capsule_types` through `gen_bindings`) (#121). ### Changed [Section titled “Changed”](#changed-32) * CI pinned to Node 22 LTS across all workflows. `tree-sitter@0.25.0` (the `tree-sitter` npm package) ships a `binding.cc` written against pre-C++20 stdlib (no `std::ranges`, `concept`, `requires`) and fails to compile against Node 24/26’s V8 headers. Node 22 is the latest supported runtime until upstream `node-tree-sitter` updates its `cflags_cc` or ships prebuilds. * CPD pre-commit hook and `packages/java/pom.xml` `maven-pmd-plugin` minimum-tokens bumped from 100 → 250: alef’s java codegen emits \~200-token `try`/`catch` cleanup blocks on `DownloadManager` / `LanguageRegistry`. Refactoring the codegen to share a helper is tracked separately. ## 1.8.0 - 2026-05-09 [Section titled “1.8.0 - 2026-05-09”](#180---2026-05-09) ### Added [Section titled “Added”](#added-9) * macOS x86\_64 native binaries across all polyglot bindings (Python wheels, npm napi, Ruby gem, Maven JAR, NuGet, C FFI, Go FFI, libts-pack bottle) — restores Intel Mac coverage that was missing under the alef 0.11 transition * Real Homebrew bottle protocol for both `ts-pack` (CLI) and `libts-pack` (FFI library) via `brew install --build-bottle` + `brew bottle --json`, replacing the prior synthetic tarball approach. Eight bottles per release across `arm64_sequoia`, `sequoia`, `arm64_linux`, `x86_64_linux`. `brew install` now pours instead of source-building * `libts-pack` Homebrew formula bundling tree-sitter language pack as a C library (headers + dylib/so + static archive) * Python sdist published to PyPI alongside the existing platform wheels * E2E fixtures covering Kotlin package + class structure (`kotlin_package_class_intel.json`), Java package declarations (`java_package_intel.json`), and a process call exercising the typed `extractions` map (`process_with_extractions.json`) ### Changed [Section titled “Changed”](#changed-33) * Migrated to alef 0.15.x (Jinja-based codegen) for all polyglot bindings — Python, TypeScript, Ruby, Go, Java, C#, Elixir, PHP, WASM * WASM now ships the `--target nodejs` build to npm so consumers no longer hit the bundler-only `import * from "env"` failure on `require()` * WASM coverage scoped to a curated 32-language subset to fit the 16 GB GitHub runner during builds ### Fixed [Section titled “Fixed”](#fixed-36) * Intel: emit `StructureKind::Module` for Kotlin `package_header` and Java `package_declaration` so callers can build fully-qualified names for JVM languages (#112) * Intel: resolve structure names via a fallback chain (`name` field → `type_identifier` → `identifier` → `scoped_identifier`) so Kotlin classes and Java/Kotlin packages no longer surface with null names (#111) * Java: ship `natives/{rid}/` entries inside the published JAR — `actions/download-artifact` produces nested artifact paths, and the previous staging loop preserved them, so every platform hit `UnsatisfiedLinkError` on load. Flatten via `find` and add presence/`jar tf` guard steps so the regression cannot ship silently again (#114) * Bindings: surface `extractions` as a typed `Map` / `Map` across Java, Python, Go, TypeScript, Ruby, PHP, C#, Elixir, FFI, and WASM (was `Optional` on Java, blocking pattern extractions through the high-level API). Driven by the alef 0.12.4 codegen fix for `AHashMap`-typed fields (#115) * C#: strip duplicate `{` lines emitted by alef 0.14.33 codegen so generated `.cs` files compile * Ruby: regenerated `native.rb` no longer recurses into itself via `define_singleton_method` — magnus codegen now skips re-export when binding name matches the native module method * Node: `index.js` now contains real platform-dispatch logic so `require()` resolves the correct `.darwin-arm64.node`/`.linux-x64-gnu.node`/etc. instead of failing on the un-suffixed bundle name * WASM: drop bundler-only output, removing spurious `'env'` module imports that broke `require()` from Node consumers * Maven JAR previously missed `linux-x86_64` natives because of stage-loop path mishandling; flatten artifact downloads and add a `jar tf` guard * Hex.pm `metadata.config` size limit — exclude the parser sources tarball from the package * PHP: fix broken `crates/ts-pack-php/README.md` links in root `README.md` — path moved to `packages/php/README.md` after alef migration (#106) * PHP: fix `.task/php.yml` `build`, `build:dev`, and `clean` tasks pointing to removed `crates/ts-pack-php/` — corrected to `crates/ts-pack-core-php/` (#106) * PHP: align `packages/php/composer.json` and `packages/php/README.md` package name to canonical Packagist vendor slug (`kreuzberg/` not `xberg-io/`) (#106) * PHP: document `mlocati/php-extension-installer` prerequisite in install docs and correct minimum PHP version to 8.4+ (#106) * Go: regenerate stale `binding.go` with current alef generator ## 1.7.0 - 2026-04-22 [Section titled “1.7.0 - 2026-04-22”](#170---2026-04-22) ### Added [Section titled “Added”](#added-10) * Migrate to [alef](https://github.com/xberg-io/alef) polyglot binding generator — all language bindings (Python, TypeScript, Ruby, Go, Java, C#, Elixir, PHP, WASM) are now generated from a single `alef.toml` configuration * `Default`, `Hash`, `PartialEq`, `Eq` derives on all public types * 18 new e2e test fixtures closing testing gaps across all binding languages * Consolidated CI: 12 language-specific workflows merged into a single `ci.yaml` * Registry-mode e2e test apps under `test_apps/` (generated via `alef e2e generate --registry`) ### Changed [Section titled “Changed”](#changed-34) * Public API locked down with `pub(crate)` — only functions and types that were in the pre-alef Python bindings are exported; internal modules (`json_utils`, `intel` submodules, `config`, `definitions`) are no longer public * Workspace lints applied to all binding crates (`clippy::all = "deny"`, `unsafe_code = "deny"`) * `test_apps/` moved from `tests/test_apps/` to project root ### Fixed [Section titled “Fixed”](#fixed-37) * `available_languages()`, `has_language()`, and `language_count()` now register the download cache directory before querying the registry — fixes empty results when using the `download` feature (#90) * `process()` auto-downloads missing parsers instead of returning `LanguageNotFound` (#94) * C# task references updated from `.sln` to `.csproj` * Maven version plugin pinned to exclude alpha/beta/RC versions * Docker CI: `uv run` changed to `uv run --no-project` to avoid triggering root pyproject.toml build * Ruby CI: removed stale `working-directory` that pointed to wrong path ## 1.6.3 - 2026-04-20 [Section titled “1.6.3 - 2026-04-20”](#163---2026-04-20) ### Fixed [Section titled “Fixed”](#fixed-38) * Go: fix FFI build defaults — add `TSLP_LINK_MODE` and `TSLP_LANGUAGES` env vars to Go task (#102) * Go: fix CGO `LDFLAGS` paths — point to workspace `target/release/` instead of crate-local path (#102) * Go: remove duplicate forward declarations from `ffi.go` (already in `ts_pack.h`) (#102) * Go: fix README examples — proper error handling, correct API signatures (`Init`, `Download`) (#102) * FFI: add extra libs dir from `cache_dir()` to registry on creation (#102) * Docs: fix textlint pre-commit hook — add `additional_dependencies` for all textlint plugins (#102) ## 1.6.2 - 2026-04-18 [Section titled “1.6.2 - 2026-04-18”](#162---2026-04-18) ### Fixed [Section titled “Fixed”](#fixed-39) * Compile bundled grammars with `-fno-strict-aliasing` to prevent undefined behavior (#100) ### Changed [Section titled “Changed”](#changed-35) * Update dependencies across lockfiles * Regenerate READMEs for 1.6.1 version bump (#101) ## 1.6.1 - 2026-04-17 [Section titled “1.6.1 - 2026-04-17”](#161---2026-04-17) ### Fixed [Section titled “Fixed”](#fixed-40) * Go: move package root from `packages/go/v1/` to `packages/go/` so the Go module proxy can resolve `go.mod` at the correct path — `go get github.com/xberg-io/tree-sitter-language-pack/packages/go` now works (#97) * Go: fix CGO `SRCDIR`-relative include/lib paths (one fewer `../` after directory restructure) * Remove `features = ["all"]` from e2e Rust test `Cargo.toml` — use `download` feature for runtime parser fetching * Remove 305 `lang-*` features to unblock crates.io publish (300 feature limit) * Regenerate READMEs for v1.6.0, fix Windows query cache test flake * Bump `rustls-webpki` to patch RUSTSEC-2026-0098 and RUSTSEC-2026-0099 (#99) * Fix MIME type inference in core build by embedding `language_definitions.json` in crate ### Changed [Section titled “Changed”](#changed-36) * Update dependencies across Python, Node.js, PHP, and Rust lockfiles * Replace feature group docs with `download`/`TSLP_LANGUAGES` documentation in READMEs ## 1.6.0 - 2026-04-14 [Section titled “1.6.0 - 2026-04-14”](#160---2026-04-14) ### Added [Section titled “Added”](#added-11) * Thread-local parser cache in `parse_string()` — avoids re-creating parsers on repeated calls for the same language * Two-level compiled query cache (thread-local + global) in `run_query()` — avoids recompiling tree-sitter queries * `parse_with_language()` internal API for callers that already have a `Language` object * Pre-computed capture names in `CompiledExtraction` — avoids rebuilding on every extraction call * Go `type_spec` declarations extracted as symbols with correct `SymbolKind` (struct, interface, type) * Dedicated “Download Parsers” section in quickstart docs covering CLI, programmatic APIs, groups, Docker/CI, and config files * Tests for parser cache reuse, query cache sharing across threads, cursor byte-range isolation, and capture name correctness ### Fixed [Section titled “Fixed”](#fixed-41) * `compiled_query()` now propagates `Error::LockPoisoned` instead of silently ignoring poisoned RwLock * `QueryCursor` byte-range no longer leaks between patterns when reusing the cursor in `extract_from_tree()` * Replaced `std::collections::HashMap` with `ahash::AHashMap` in parser cache for consistency * Redundant `get_language()` call removed from `parse_string()` hot path — only called on cache miss ### Changed [Section titled “Changed”](#changed-37) * `CompiledExtraction::extract()` and `intel::parse_source()` now use the thread-local parser cache * `QueryCursor` reused across patterns within a single `extract_from_tree()` call * Unnecessary `String` allocation removed from `node_types.contains()` check in chunking ### Removed [Section titled “Removed”](#removed-4) * All 305 `lang-*` Cargo features and group features (`all`, `web`, `systems`, `scripting`, `data`, `jvm`, `functional`, `wasm`) — language selection is now via `TSLP_LANGUAGES` env var at build time; the `download` feature (default) fetches parsers at runtime ## 1.5.0 - 2026-04-08 [Section titled “1.5.0 - 2026-04-08”](#150---2026-04-08) ### Added [Section titled “Added”](#added-12) * 57 new permissively-licensed grammars — 305 languages total * abl, c3, cel, cfml, chuck, cst, dhall, elvish, gap, gdshader, glimmer, gnuplot, gotmpl, gowork, gpg, hjson, hocon, hoon, htmldjango, jai, javadoc, json5, kcl, mlir, nasm, norg\_meta, ocamllex, openscad, phpdoc, poe\_filter, prql, rasi, razor, rbs, roc, rtf, slang, smalltalk, sml, snakemake, souffle, sourcepawn, sql\_bigquery, stan, superhtml, sway, systemverilog, tact, tera, typespec, typoscript, vhs, vrl, wgsl\_bevy, x86asm, ziggy, ziggy\_schema * CI license validation job in `ci-validate.yaml` — blocks PRs that introduce non-permissive (GPL/AGPL/LGPL/MPL) grammars ### Fixed [Section titled “Fixed”](#fixed-42) * `less` grammar: regenerated parser from ABI 11 to ABI 14 (was incompatible with tree-sitter 0.26) * `corn` smoke fixture: replaced invalid `"x"` snippet with valid corn syntax ## 1.4.1 - 2026-03-31 [Section titled “1.4.1 - 2026-03-31”](#141---2026-03-31) ### Fixed [Section titled “Fixed”](#fixed-43) * Include `language_definitions.json` in the published crate so `build.rs` can find extension mappings, ambiguity data, and C symbol overrides when installed from crates.io ### Changed [Section titled “Changed”](#changed-38) * Updated dependencies across all language ecosystems ## 1.4.0 - 2026-03-29 [Section titled “1.4.0 - 2026-03-29”](#140---2026-03-29) ### Fixed [Section titled “Fixed”](#fixed-44) * Expose `detect_language` in Python public API (#85) * PHP extension name corrected to `ts-pack-php` (hyphens) ### Changed [Section titled “Changed”](#changed-39) * All language snippet READMEs and documentation corrected * Removed automated grammar updates workflow ## 1.3.3 - 2026-03-27 [Section titled “1.3.3 - 2026-03-27”](#133---2026-03-27) ### Fixed [Section titled “Fixed”](#fixed-45) * `C_SYMBOL_OVERRIDES` table now includes ALL languages from `language_definitions.json`, not just compiled ones — fixes download and loading of `csharp`, `vb`, `embeddedtemplate`, `nushell` from PyPI/npm/RubyGems packages * `downloaded_languages()` returns canonical names (`csharp`) instead of c\_symbol names (`c_sharp`) * Elixir NIF publish: upload both hyphen and underscore artifact names so RustlerPrecompiled can find them * Elixir NIF 2.17 packaging: fix stale variable names from dual-name refactor * Ruby comprehensive test: remove `JSON.parse` on native Hash return from `process()` * Go comprehensive test: access flat `ProcessResult` fields directly (no `metadata` wrapper) * Homebrew bottle and PHP PIE packages now included in release artifacts ### Changed [Section titled “Changed”](#changed-40) * Dependency updates across all language ecosystems * `rustler_precompiled` updated to 0.9.0 (Elixir) ## 1.3.2 - 2026-03-26 [Section titled “1.3.2 - 2026-03-26”](#132---2026-03-26) ### Fixed [Section titled “Fixed”](#fixed-46) * Dynamic parser loading for languages with `c_symbol` overrides (`csharp`, `vb`, `embeddedtemplate`, `nushell`) — build was naming libraries with the raw name but runtime loader expected the `c_symbol` name (#80) * Go E2E generator: unused `tspack` import in non-process test files * Elixir: add missing `extract/2` and `validate_extraction/1` NIF declarations * PHP E2E generator: use double-quoted strings for source code so `\n` is interpreted correctly * Nim grammar: switch from abandoned `paranim/tree-sitter-nim` (ABI v11) to `aMOPel/tree-sitter-nim` (MIT, ABI v14) ### Added [Section titled “Added”](#added-13) * Smoke test fixtures for all `c_symbol` override languages (csharp, vb, embeddedtemplate, nushell) * Dynamic-linking CI step in `ci-all-grammars.yaml` to catch `c_symbol` naming mismatches ## 1.3.1 - 2026-03-26 [Section titled “1.3.1 - 2026-03-26”](#131---2026-03-26) ### Fixed [Section titled “Fixed”](#fixed-47) * Ruby binding: `process()`, `extract()`, `validate_extraction()` now return native Ruby Hash instead of raw JSON string * WASM binding: output keys now use camelCase (matching Node.js binding convention), input config accepts both camelCase and snake\_case * Go E2E generator: use typed `*ProcessResult` struct fields instead of invalid `json.Unmarshal` on non-string return * Elixir CI: stage NIF with both hyphenated and underscored filenames to satisfy Rustler force-build check and `load_from` loader ## 1.3.0 - 2026-03-26 [Section titled “1.3.0 - 2026-03-26”](#130---2026-03-26) ### Added [Section titled “Added”](#added-14) * Extraction query API: run user-defined tree-sitter queries and get structured results * `extract_patterns()` / `extract()` across Python, Node.js, Rust, Ruby, Elixir, PHP, WASM, C FFI * `validate_extraction()` for config validation without execution * `CompiledExtraction` for pre-compiled query reuse (Rust) * `ProcessConfig.extractions` for combining custom queries with standard analysis * Types: ExtractionConfig, ExtractionPattern, CaptureOutput, CaptureResult, MatchResult, PatternResult, ExtractionResult * Criterion benchmarks: 9 groups, 23 benchmarks across Python, TypeScript, Rust, Go * Extraction queries guide and documentation across all API references ### Fixed [Section titled “Fixed”](#fixed-48) * E2E generator: `process_imports_contains_source` assertion uses contains instead of equality * WASM: language list matches actual compiled features (30 languages) * WASM: add missing `detectLanguageFromPath` and `detectLanguageFromExtension` exports * PHP generator: null array handling in `process()` result assertions * Elixir: RustlerPrecompiled `crate` field resolution with `load_from` override * Predicate evaluation: remove redundant re-evaluation (tree-sitter 0.26 handles internally) * Documentation: stale version numbers, incomplete API references, incorrect function signatures * Java version requirement standardized to JDK 25+ ## 1.2.1 - 2026-03-25 [Section titled “1.2.1 - 2026-03-25”](#121---2026-03-25) ### Fixed [Section titled “Fixed”](#fixed-49) * Nushell grammar `c_symbol` override — linker error `undefined symbol: tree_sitter_nushell` * E2E generator calling `.as_deref()` on `String` type (compile error on CI) * WASM build: gate `c_symbol_for` behind `dynamic-loading`/`download` features (dead code warning) * Elixir publish: align RustlerPrecompiled `crate:` field with Cargo `[lib]` name (underscores, not hyphens) * Elixir publish: add `--cfg` flag patch to publish workflow for Rustler 0.37.3 compatibility * Python `without_gil()`: add `catch_unwind` to ensure GIL is reacquired on panic * Text splitter: prevent zero-width chunks in pathological UTF-8 edge case * Comment kind detection: handle `//!`, `/*!`, and `doc_comment` node types * Import detection: restrict fallback to explicitly supported languages only * Export detection: use field-based AST matching instead of fragile `text.contains()` ### Changed [Section titled “Changed”](#changed-41) * Registry: `Arc>` for extra lib dirs (avoids Vec clone per language lookup) * Registry: `AHashSet<&str>` in `available_languages()` (avoids 248+ String allocations) * `NodeInfo.kind` uses `Cow::Borrowed` (zero-copy from tree-sitter’s `&'static str`) * Python: `with_tree()`/`try_with_tree()` helpers replace 9 duplicate lock patterns * Python: `without_gil()` helper replaces 5 duplicate GIL release patterns * Core: `extension_ambiguity_json()` helper replaces duplicated JSON serialization in 4 bindings * Chunking: `MetadataCollector` struct reduces function from 11 to 7 parameters * FFI: 25 SAFETY comments added to unsafe blocks * Docs: rewrite all 12 API references to match actual binding source code * Docs: add JSON-LD structured data and Open Graph metadata for crawlers ## 1.2.0 - 2026-03-25 [Section titled “1.2.0 - 2026-03-25”](#120---2026-03-25) ### Added [Section titled “Added”](#added-15) * 49 new permissively-licensed grammars — 248 languages total * angular, bass, blade, brightscript, circom, cooklang, corn, crystal, cue, cylc, desktop, djot, earthfile, ebnf, editorconfig, eds, eex, elsa, enforce, facility, faust, fidl, foam, forth, git\_config, git\_rebase, godot\_resource, http, hurl, just, ledger, less, liquid, mojo, move, nickel, nginx, norg, nushell, promql, pug, ql, robot, teal, templ, tmux, todotxt, turtle, vimdoc, wolfram * Grammar updater automation (`scripts/check_grammar_updates.py`) with weekly CI workflow * Generated supported languages table (`docs/supported-languages.md`) integrated into docs CI * Node.js NAPI exports: `detectLanguageFromExtension`, `detectLanguageFromPath`, `getHighlightsQuery`, `extensionAmbiguity` * E2E `process` test category with `process()` API coverage across all 11 language bindings ### Fixed [Section titled “Fixed”](#fixed-50) * Download/load filename mismatch for languages with c\_symbol overrides (csharp, embeddedtemplate, vb) — fixes [#80](https://github.com/xberg-io/tree-sitter-language-pack/issues/80) * E2E fixture system: merged stale `intel/` and `metadata/` directories into unified `process/` category * TypeScript and WASM e2e generators now use camelCase for metrics keys * Docker CI grammar fixture updated to include all languages * Elixir publish workflow: checksum file verification, increased retry timeout * Missing Node.js `index.js` exports for detection and query functions ### Changed [Section titled “Changed”](#changed-42) * Renamed e2e fixture assertions from `intel_*`/`meta_*` to `process_*` * All documentation and package descriptions updated to reflect 248 languages ## 1.1.4 - 2026-03-24 [Section titled “1.1.4 - 2026-03-24”](#114---2026-03-24) ### Added [Section titled “Added”](#added-16) * New language: `al` (AL / Business Central) — 198 languages total * Grammar license linter (`scripts/lint_grammar_licenses.py`, `task lint:licenses`) verifies all grammars use permissive licenses * Permissive license policy documented in CONTRIBUTING.md, docs, and README ### Fixed [Section titled “Fixed”](#fixed-51) * Replace `nim` grammar (alaviss, MPL-2.0 copyleft) with paranim/tree-sitter-nim (MIT) * Replace `prolog` grammar (codeberg foxy, AGPL-3.0 copyleft) with Rukiza/tree-sitter-prolog (ISC) * Docs: align mkdocs config with kreuzberg branding; mermaid diagrams now render (fixes [#81](https://github.com/xberg-io/tree-sitter-language-pack/issues/81)) ## 1.1.3 - 2026-03-24 [Section titled “1.1.3 - 2026-03-24”](#113---2026-03-24) ### Fixed [Section titled “Fixed”](#fixed-52) * Dynamic loader: resolve `c_symbol` overrides for csharp, embeddedtemplate, and vb so `get_language()` works for dynamically loaded grammars (fixes [#80](https://github.com/xberg-io/tree-sitter-language-pack/issues/80)) * E2E generator: enable all ProcessConfig features (structure, imports, exports, comments, docstrings, symbols, diagnostics) for intel tests so diagnostics assertions pass ### Added [Section titled “Added”](#added-17) * 23 new smoke test fixtures for languages missing coverage: asciidoc, awk, batch, caddy, cedar, cedarschema, csharp, devicetree, diff, dot, embeddedtemplate, idris, jinja2, jq, lean, pkl, postscript, prolog, rescript, ssh\_config, textproto, tlaplus, vb, wit, zsh * CI workflow (`ci-all-grammars.yaml`) that tests all 197 grammars end-to-end, preventing regressions like #80 * `rust:e2e:all-grammars` task for running the full grammar suite locally ## 1.1.2 - 2026-03-23 [Section titled “1.1.2 - 2026-03-23”](#112---2026-03-23) ### Fixed [Section titled “Fixed”](#fixed-53) * Elixir NIF: fix Rustler crate name mismatch (`ts_pack_elixir` → `ts-pack-elixir`) causing compilation failure * Rust crate publish: embed query file contents at build time instead of using `include_str!` with relative paths that break in the cargo package tarball ## 1.1.1 - 2026-03-23 [Section titled “1.1.1 - 2026-03-23”](#111---2026-03-23) ### Fixed [Section titled “Fixed”](#fixed-54) * WASM build: ahash uses compile-time-rng instead of runtime-rng (avoids getrandom on wasm32) * Docker/static build: add `c_symbol` override for grammars with non-standard C symbol names (csharp, vb, embeddedtemplate) * Unused imports when `dynamic-loading` feature disabled (WASM builds) * Python sdist: `.pyi` and `py.typed` now included in both wheel and sdist * C# build: add missing `ExtensionAmbiguityResult` model class * Set `generate: true` for csharp, vb, embeddedtemplate grammars ### Changed [Section titled “Changed”](#changed-43) * Switch from `std::HashMap`/`HashSet` to `ahash::AHashMap`/`AHashSet` for faster hashing in registry ## 1.1.0 - 2026-03-23 [Section titled “1.1.0 - 2026-03-23”](#110---2026-03-23) ### Added [Section titled “Added”](#added-18) * 20 new languages from arborium: asciidoc, awk, caddy, cedar, cedarschema, devicetree, dot, idris, jinja2, jq, lean, postscript, prolog, rescript, ssh\_config, textproto, tlaplus, vb, wasm-interface-types, zsh (197 total) * Centralized extension-to-language mapping: `sources/language_definitions.json` is the single source of truth for 239 file extensions across 197 languages * Build-time code generation: `build.rs` generates extension lookup with strict validation (panics on duplicates, non-ASCII, uppercase, dots) * `detect_language_from_content(content)`: shebang-based language detection (`#!/usr/bin/env python3` → “python”) * `extension_ambiguity(ext)`: query whether a file extension is ambiguous (e.g. `.m` → objc with matlab alternative) * Highlight query bundling: `get_highlights_query(lang)`, `get_injections_query(lang)`, `get_locals_query(lang)` — embed .scm queries at build time * `ambiguous` field in `language_definitions.json` for declaring known extension ambiguities * E2E test fixtures and generators for detect-language, ambiguity, and highlights across all 11 language targets * New APIs exposed in all bindings: Python, Node.js, Ruby, WASM, Elixir, PHP, C FFI, Go, C# ### Changed [Section titled “Changed”](#changed-44) * `LanguageRegistry` uses `Arc>>` for interior mutability — no more global `RwLock` wrapper, eliminates lock poisoning risk * `ProcessConfig.language`: `String` → `Cow<'static, str>` (zero allocation for string literals) * `NodeInfo.kind`, `QueryMatch.captures`: `String` → `Cow<'static, str>` * `available_languages()` uses `HashSet` for O(1) dedup instead of O(n) Vec contains * Chunking line counting uses precomputed newline table with binary search (O(log n) per chunk vs O(n)) * Added `memchr` dependency for fast byte scanning in text splitter and chunking * Extension/ambiguity lookups generated from JSON at build time * `clone_vendors.py` now copies `queries/` directories alongside `src/` ### Fixed [Section titled “Fixed”](#fixed-55) * Strong types in all binding stubs: Python `.pyi` (TypedDicts), TypeScript `.d.ts` (interfaces), Ruby `.rbs` (record types), C# `Models.cs` (string enums replace `object`) * Pre-existing registry test failures from global `RwLock` poisoning — test helpers now use local `LanguageRegistry::new()` * Removed ambiguous `.os` (bsl) and `.cls` (apex/LaTeX conflict) extensions ## 1.0.0 - 2026-03-21 [Section titled “1.0.0 - 2026-03-21”](#100---2026-03-21) ### Changed [Section titled “Changed”](#changed-45) * Docker: separated publish-docker workflow from main publish (180-minute timeout for multiplatform builds) * Docker: publish-docker now triggers on `release` events and includes full smoke tests before push * Test apps: all bindings now download languages before running tests (Ruby, Go, Elixir) * Test apps: Rust test app adds parse\_string validation tests * Test apps: CLI smoke test adds chunking test * Test apps: added Homebrew smoke test suite ### Fixed [Section titled “Fixed”](#fixed-56) * npm publish authentication and registry configuration * Elixir NIF binary build and checksum generation * Ruby CI and WASM build timeout * Version sync across binding manifests *** ## Pre-1.0 Releases (Python-only) [Section titled “Pre-1.0 Releases (Python-only)”](#pre-10-releases-python-only) ### 0.12.0 [Section titled “0.12.0”](#0120) #### Added [Section titled “Added”](#added-19) * tree-sitter-cobol grammar support #### Fixed [Section titled “Fixed”](#fixed-57) * MSVC build compatibility for cobol grammar * Alpine Linux (musl) wheel platform tag support (PEP 656) * Wheel file discovery in CI test action ### 0.11.0 [Section titled “0.11.0”](#0110) #### Added [Section titled “Added”](#added-20) * tree-sitter-bsl (1C:Enterprise) grammar support #### Changed [Section titled “Changed”](#changed-46) * Updated all dependencies and relocked ### 0.10.0 [Section titled “0.10.0”](#0100) #### Added [Section titled “Added”](#added-21) * tree-sitter 0.25 support #### Changed [Section titled “Changed”](#changed-47) * Dropped Python 3.9 support * Adopted prek pre-commit workflow * CI: cancel superseded workflow runs ### 0.9.1 [Section titled “0.9.1”](#091) #### Added [Section titled “Added”](#added-22) * WASM (wast & wat) grammar support * F# and F# signature grammar support ### 0.9.0 [Section titled “0.9.0”](#090) #### Added [Section titled “Added”](#added-23) * tree-sitter-nim grammar support * tree-sitter-ini grammar support * Swift grammar update (trailing comma support) ### 0.8.0 [Section titled “0.8.0”](#080) #### Fixed [Section titled “Fixed”](#fixed-58) * sdist build issues resolved ### 0.7.4 [Section titled “0.7.4”](#074) #### Added [Section titled “Added”](#added-24) * GraphQL grammar support * Kotlin grammar support (SAM conversions) * Netlinx grammar support ### 0.7.3 [Section titled “0.7.3”](#073) #### Changed [Section titled “Changed”](#changed-48) * Swift grammar update (macros + copyable) ### 0.7.2 [Section titled “0.7.2”](#072) #### Added [Section titled “Added”](#added-25) * Apex grammar support #### Fixed [Section titled “Fixed”](#fixed-59) * MSYS2 GCC build issues ### 0.7.1 [Section titled “0.7.1”](#071) #### Added [Section titled “Added”](#added-26) * OCaml and OCaml Interface grammar support * Markdown inline parser support #### Fixed [Section titled “Fixed”](#fixed-60) * Pinned elm and rust grammar versions * Pinned tree-sitter-tcl to known-good revision ### 0.6.1 [Section titled “0.6.1”](#061) #### Added [Section titled “Added”](#added-27) * ARM64 Linux CI builds #### Fixed [Section titled “Fixed”](#fixed-61) * Build issue resolved ### 0.6.0 [Section titled “0.6.0”](#060) #### Fixed [Section titled “Fixed”](#fixed-62) * Windows DLL loading compatibility issues ### 0.5.0 [Section titled “0.5.0”](#050) #### Fixed [Section titled “Fixed”](#fixed-63) * Windows compatibility and encoding issues for non-English locales ### 0.4.0 [Section titled “0.4.0”](#040) #### Added [Section titled “Added”](#added-28) * PyCapsule-based language loading * Protocol Buffers (proto) grammar support * SPARQL grammar support ### 0.3.0 [Section titled “0.3.0”](#030) #### Changed [Section titled “Changed”](#changed-49) * Updated generation setup and build matrix * Removed magik and swift grammars (temporarily) ### 0.2.0 [Section titled “0.2.0”](#020) #### Changed [Section titled “Changed”](#changed-50) * Version bump with dependency updates ### 0.1.2 [Section titled “0.1.2”](#012) #### Fixed [Section titled “Fixed”](#fixed-64) * Added MANIFEST.in for sdist packaging ### 0.1.1 [Section titled “0.1.1”](#011) #### Fixed [Section titled “Fixed”](#fixed-65) * Missing parsers in package data ### 0.1.0 [Section titled “0.1.0”](#010) #### Added [Section titled “Added”](#added-29) * Initial release with 100+ tree-sitter language grammars * Python package with pre-compiled parsers * Multi-platform wheel builds (Linux, macOS, Windows) # Architecture > How tree-sitter-language-pack is structured: Rust core, thin binding layer, and the download system. Tree-sitter-language-pack follows a layered architecture: a single Rust core library handles all parsing logic, and thin binding layers expose that API natively in each target language. No business logic lives in the bindings — they are pure translation layers. *** ## High-Level Diagram [Section titled “High-Level Diagram”](#high-level-diagram) ```mermaid graph TD subgraph Bindings["Language Bindings"] PY["Python
(PyO3 / maturin)"] NODE["Node.js
(NAPI-RS)"] RB["Ruby
(Magnus)"] EL["Elixir
(Rustler NIF)"] PHP["PHP
(ext-php-rs)"] WASM["WebAssembly
(wasm-bindgen)"] FFI["C FFI
(cbindgen)"] DART["Dart
(flutter_rust_bridge)"] SWIFT["Swift
(swift-bridge)"] end subgraph FFIConsumers["FFI Consumers"] GO["Go
(cgo)"] JAVA["Java
(Panama FFM)"] CS["C# / .NET
(P/Invoke)"] KOTLIN["Kotlin Android
(JNI / AAR)"] ZIG["Zig
(C ABI)"] end subgraph Core["Rust Core (ts-pack-core)"] DL["Download Manager"] CACHE["Parser Cache"] PROC["Code Intelligence Engine"] CHUNK["Chunker"] TS["tree-sitter runtime"] end subgraph Parsers["Parser Binaries (remote)"] MANIFEST["parsers.json manifest"] BIN["Platform-specific .so / .dll / .dylib"] end PY --> Core NODE --> Core RB --> Core EL --> Core PHP --> Core WASM --> Core DART --> Core SWIFT --> Core FFI --> Core GO --> FFI JAVA --> FFI CS --> FFI KOTLIN --> FFI ZIG --> FFI DL -->|"HTTPS download"| MANIFEST DL -->|"fetch binary"| BIN CACHE -->|"dlopen"| BIN Core --> TS ``` *** ## Rust Core [Section titled “Rust Core”](#rust-core) All logic lives in a single crate: `crates/ts-pack-core`. | Component | Responsibility | | ---------------------------- | ----------------------------------------------------------------------------------------------------------------------------- | | **Download Manager** | Resolves the remote manifest, fetches platform-specific parser binaries, stores them in the local cache. | | **Parser Cache** | Maps language names to loaded `tree_sitter::Language` values. Once loaded, a parser is reused without re-reading from disk. | | **Code Intelligence Engine** | Walks parsed ASTs to extract structure, imports, exports, symbols, comments, docstrings, data trees, diagnostics, and chunks. | | **Chunker** | Walks the syntax tree and splits source code at natural boundaries, respecting a configurable token budget. | The core has no language-specific code. It calls tree-sitter through its stable C ABI using dynamically loaded parser binaries. *** ## Binding Layer [Section titled “Binding Layer”](#binding-layer) Each binding is a thin crate that: 1. Calls Rust core functions. 2. Converts Rust types to the target language’s native types (`String` → `str`, `Vec` → list/array, `Result` → exception/error). 3. Exposes an idiomatic API matching the target language’s conventions. Binding crates contain no parsing logic, no query definitions, and no chunking code. | Location | Framework | Distribution | | -------------------------- | --------------------- | -------------------- | | `crates/ts-pack-core-py` | PyO3 + maturin | PyPI wheels | | `crates/ts-pack-core-node` | NAPI-RS | npm (multi-platform) | | `packages/ruby` | Magnus | RubyGems native gem | | `packages/elixir` | Rustler NIF | Hex.pm | | `crates/ts-pack-core-php` | ext-php-rs | Packagist | | `crates/ts-pack-core-wasm` | wasm-bindgen | npm (Wasm) | | `crates/ts-pack-core-ffi` | cbindgen (C FFI) | GitHub releases | | `packages/go` | cgo | Go modules | | `packages/java` | Panama FFM | Maven Central | | `packages/csharp` | P/Invoke | NuGet | | `packages/dart` | flutter\_rust\_bridge | pub.dev | | `packages/kotlin-android` | JNI / Android AAR | Maven Central | | `packages/swift` | swift-bridge | SwiftPM | | `packages/zig` | C ABI wrapper | Zig package | *** ## Parser Binaries [Section titled “Parser Binaries”](#parser-binaries) Native packages do not compile the full parser set into the package. Instead: 1. A `parsers.json` manifest (on GitHub releases) lists one bundle per target platform plus per-language metadata for all 371 grammars. 2. On first use, the matching platform bundle downloads and extracts to the local cache directory. 3. The runtime opens the relevant grammar binary via `dlopen` / `LoadLibrary` and resolves the `tree_sitter_` symbol. This keeps installation fast and download sizes minimal. See [Download Model](/concepts/download-model/) for the full detail. The WebAssembly package is the exception: it uses a curated static parser subset compiled into the `.wasm` module and does not expose native download/cache helpers. *** ## ABI Compatibility [Section titled “ABI Compatibility”](#abi-compatibility) Bundled grammars are compiled at tree-sitter **ABI version 14**, with 16 exceptions at ABI 15 whose committed `parser.c` is too large to regenerate: `abl`, `cpp`, `csharp`, `fsharp`, `fortran`, `gnuplot`, `haxe`, `jai`, `lean`, `perl`, `postgres`, `razor`, `scala`, `slang`, `systemverilog`, and `zsh`. Those 16 require a tree-sitter runtime >=0.25; see [Languages](/languages/#abi-compatibility). ABI 14 is accepted by tree-sitter runtimes spanning versions 0.21 through 0.26, and by the following host tree-sitter packages (used via host-native Language passthrough): * **Python**: `tree-sitter` >=0.23 * **Node.js**: `tree-sitter` latest (matches node-tree-sitter’s embedded tree-sitter version) * **Go**: `go-tree-sitter` v0.24.0+ * **Java**: `jtreesitter` 0.26.0+ * **C#**: `TreeSitter.DotNet` 1.3.0+ * **Kotlin/Android**: `ktreesitter` 0.25.0+ * **Swift**: `SwiftTreeSitter` 0.25.0+ * **Zig**: `zig-tree-sitter` v0.26.0+ * **C**: `libtree-sitter` (any ABI 14-compatible runtime; `get_language()` returns the bare `const TSLanguage *`) This wide compatibility window ensures the language pack works across a broad ecosystem of tree-sitter consumers without requiring version pinning or ecosystem-specific grammar patches. *** ## Repository Layout [Section titled “Repository Layout”](#repository-layout) ```text tree-sitter-language-pack/ ├── crates/ │ ├── ts-pack-core/ # Rust core library │ ├── ts-pack-cli/ # CLI binary │ ├── ts-pack-core-py/ # Python (PyO3) binding │ ├── ts-pack-core-node/ # Node.js (NAPI-RS) binding │ ├── ts-pack-core-php/ # PHP (ext-php-rs) extension │ ├── ts-pack-core-wasm/ # WebAssembly (wasm-bindgen) binding │ └── ts-pack-core-ffi/ # C FFI for native-package consumers ├── packages/ │ ├── python/ # Python package wrapper │ ├── ruby/ # Ruby gem (Magnus NIF) │ ├── elixir/ # Elixir package (Rustler NIF) │ ├── php/ # PHP Composer package │ ├── go/ # Go module (cgo wrapper) │ ├── java/ # Java package (Panama FFM) │ ├── csharp/ # C# / .NET package (P/Invoke) │ ├── dart/ # Dart / Flutter package │ ├── kotlin-android/ # Android AAR package │ ├── swift/ # SwiftPM package │ └── zig/ # Zig package ├── docs-site/ # Astro / Starlight documentation site ├── fixtures/ # JSON fixtures driving the generated e2e suites ├── e2e/ # Generated per-language e2e suites (do not edit) └── sources/ └── language_definitions.json # Grammar source registry ``` The Node.js and WebAssembly packages have no `packages/` directory — they are published directly from `crates/ts-pack-core-node` and `crates/ts-pack-core-wasm`. Documentation snippets under `docs-site/src/snippets/` are discovered, validated, and audited by `alef snippets`. The legacy `tools/snippet-runner` Rust crate was retired in favour of this shared capability. *** ## Design Principles [Section titled “Design Principles”](#design-principles) * **Single source of truth** — All parsing and intelligence logic lives in `ts-pack-core`. Binding crates are pure glue. * **On-demand downloads** — Parsers do not ship in the package. The pack fetches and caches them per-platform on first use. * **ABI stability** — The C FFI layer (`ts-pack-core-ffi`) follows strict semantic versioning. Native bindings depend on stable ABI handles, not Rust internals. * **Zero duplication** — Parser loading, chunking strategies, and intelligence extraction are each written once in Rust and reused across all generated language surfaces. # Code Intelligence > What tree-sitter-language-pack extracts from source code: structure, imports, exports, comments, docstrings, and chunks. The `process` function goes beyond raw syntax trees. It parses source, then the Rust core walks the AST to extract structured information useful for code analysis, search, documentation, and LLM ingestion. Bundled query helpers return query source strings; arbitrary query execution is left to host-language tree-sitter APIs. *** ## ProcessConfig [Section titled “ProcessConfig”](#processconfig) All intelligence extraction is opt-in via `ProcessConfig`. Enable what you need: * Python ```python from tree_sitter_language_pack import ProcessConfig config = ProcessConfig( language="python", structure=True, # functions, classes, methods imports=True, # import statements exports=True, # exported symbols comments=True, # inline comments docstrings=True, # docstring extraction symbols=True, # all identifiers diagnostics=True, # syntax errors / error nodes # chunk_max_size=1000 # uncomment to enable chunking ) ``` * Node.js ```typescript import { process } from "@xberg-io/tree-sitter-language-pack"; const result = process(source, { language: "typescript", structure: true, imports: true, exports: true, comments: true, docstrings: true, symbols: true, diagnostics: true, }); ``` * Rust ```rust use tree_sitter_language_pack::{process, ProcessConfig}; let config = ProcessConfig::new("rust").all(); let result = process(source, &config)?; ``` In Rust, `ProcessConfig::new("python").all()` enables everything at once (and `.minimal()` disables everything). Ruby’s `ProcessConfig` carries the same `all`, `minimal`, and `with_chunking` helpers. The public Python `ProcessConfig` (a frozen dataclass) and the Node.js `ProcessConfig` (a plain object literal) have no helpers — set the fields directly. *** ## ProcessResult Fields [Section titled “ProcessResult Fields”](#processresult-fields) ### `structure` - Functions, Classes, and Methods [Section titled “structure - Functions, Classes, and Methods”](#structure---functions-classes-and-methods) A list of top-level code constructs with their names, kinds, spans, nested children, and optionally their doc comments. ```python for item in result.structure: print(item.kind) # StructureKind — "Function" | "Class" | "Method" | ... print(item.name) # "greet" (may be None) print(item.span.start_line) # 2 (zero-indexed) print(item.span.end_line) # 5 (zero-indexed) print(item.doc_comment) # "Greet a user by name." (if docstrings=True) print(item.children) # nested items — a class's methods live here ``` `StructureKind` is a closed set serialized as a PascalCase bare string: | Kind | Languages | | ------------- | --------------------------------------------- | | `"Function"` | All languages | | `"Class"` | Python, JS/TS, Java, C#, Ruby, PHP, Kotlin, … | | `"Method"` | Same as class | | `"Interface"` | TypeScript, Java, C#, Go, Kotlin, … | | `"Struct"` | Rust, Go, C, C++, C#, … | | `"Impl"` | Rust | | `"Module"` | Elixir, Ruby, Rust, Java (package), … | | `"Enum"` | Rust, Java, C#, TypeScript, Kotlin, … | | `"Trait"` | Rust | | `"Namespace"` | C#, C++, PHP, … | Everything else is reported as `Other`, which serializes as a single-keyed object: `{"Other": "macro"}`. Spans are zero-indexed `span.start_line`, `span.end_line`, `span.start_column`, and `span.end_column` all count from 0. Add 1 before showing them next to editor line numbers. *** ### `imports` - Import Statements [Section titled “imports - Import Statements”](#imports---import-statements) All import declarations with their source module and imported names. ```python for imp in result.imports: print(imp.source) # "os" or "pathlib" print(imp.items) # ["path", "getcwd"] (empty = wildcard or bare import) print(imp.alias) # "np" for `import numpy as np`, else None print(imp.is_wildcard) # True for `from x import *` print(imp.span.start_line) ``` Example output as JSON (`items`, `alias`, and `is_wildcard` are omitted when empty/false): ```json [ { "source": "os", "is_wildcard": false, "span": { "start_line": 0, "end_line": 0, "start_byte": 0, "end_byte": 9, "start_column": 0, "end_column": 9 } }, { "source": "pathlib", "items": ["Path"], "is_wildcard": false, "span": { "start_line": 1, "end_line": 1, "start_byte": 10, "end_byte": 36, "start_column": 0, "end_column": 26 } } ] ``` *** ### `exports` — Exported Symbols [Section titled “exports — Exported Symbols”](#exports--exported-symbols) Symbols that are part of the module’s public API. ```python for exp in result.exports: print(exp.name) # "readFile" print(exp.kind) # ExportKind — "Named" | "Default" | "ReExport" print(exp.span.start_line) ``` Note Export detection is language-specific. For Python, everything defined at module level counts as exported unless prefixed with `_`. For JavaScript/TypeScript, explicit `export` declarations determine what the module exposes. *** ### `comments` - Inline Comments [Section titled “comments - Inline Comments”](#comments---inline-comments) All comments in the file with their text and location. ```python for comment in result.comments: print(comment.text) # "// Review edge case" print(comment.kind) # CommentKind — "Line" | "Block" | "Doc" print(comment.span.start_line) # 41 (zero-indexed) print(comment.associated_node) # node kind this comment attaches to, or None ``` *** ### `docstrings` - Documentation Strings [Section titled “docstrings - Documentation Strings”](#docstrings---documentation-strings) Docstrings appear both in `result.docstrings` (as `DocstringInfo` records with `text`, `format`, `span`, `associated_item`, and `parsed_sections`) and under their parent construct in `structure`. When `docstrings=True`, each `structure` item gains a `doc_comment` field: ```python func = result.structure[0] print(func.doc_comment) # "Read and return the contents of a file.\n\nArgs:\n path: Path to the file." ``` Docstring extraction understands language-specific conventions: | Language | Convention | | --------------------- | ---------------------------------------------------------------- | | Python | `"""..."""` triple-quoted string immediately after `def`/`class` | | Rust | `///` or `//!` doc comments above item | | JavaScript/TypeScript | `/** ... */` JSDoc block above function | | Java | `/** ... */` Javadoc block above method/class | | Ruby | `# ...` lines immediately above `def`/`class` | | Go | `// FuncName ...` comment block above func | | Elixir | `@doc "..."` or `@moduledoc "..."` | *** ### `symbols` - All Identifiers [Section titled “symbols - All Identifiers”](#symbols---all-identifiers) A list of `SymbolInfo` **structs** — not bare strings — useful for search indexing. ```python for symbol in result.symbols: print(symbol.name) # "read_file" print(symbol.kind) # SymbolKind — "Variable" | "Constant" | "Function" | # "Class" | "Type" | "Interface" | "Enum" | "Module" print(symbol.span.start_line) print(symbol.type_annotation) # "str", or None print(symbol.doc) # associated doc comment, or None ``` *** ### `diagnostics` - Syntax Errors [Section titled “diagnostics - Syntax Errors”](#diagnostics---syntax-errors) Tree-sitter produces partial trees for malformed code, marking error nodes. `diagnostics` surfaces these: ```python for error in result.diagnostics: print(error.message) # "Unexpected token" print(error.severity) # DiagnosticSeverity — "Error" | "Warning" | "Info" print(error.span.start_line) # zero-indexed print(error.span.start_column) # zero-indexed ``` Tip A non-empty `diagnostics` list does not mean the file is unparsable — tree-sitter recovers and continues. Use it to detect broken syntax rather than to gate parsing. *** ### `chunks` - Syntax-Aware Splits [Section titled “chunks - Syntax-Aware Splits”](#chunks---syntax-aware-splits) When `chunk_max_size` is set, the `chunks` field contains the file split into byte-budget segments. See [Chunking for LLMs](/guides/chunking/) for full documentation. ```python for chunk in result.chunks: print(chunk.content) # the source code text print(chunk.start_byte) # inclusive start byte offset print(chunk.end_byte) # exclusive end byte offset print(chunk.start_line) # first line of chunk (zero-indexed) print(chunk.end_line) # last line of chunk (zero-indexed) print(chunk.metadata.node_types) # ["function_definition", "class_definition"] print(chunk.metadata.context_path) # ["FileCache", "get"] ``` *** ### `metrics` - File-Level Statistics [Section titled “metrics - File-Level Statistics”](#metrics---file-level-statistics) Basic metrics about the file: ```python m = result.metrics print(m.total_lines) # 120 print(m.code_lines) # 95 (non-blank, non-comment lines) print(m.comment_lines) # 18 print(m.blank_lines) # 7 print(m.total_bytes) # total byte length of the source print(m.node_count) # total nodes in the syntax tree print(m.error_count) # error nodes in the syntax tree print(m.max_depth) # maximum nesting depth of the syntax tree ``` *** ## Full Example [Section titled “Full Example”](#full-example) ```python from tree_sitter_language_pack import process, ProcessConfig source = ''' import os from pathlib import Path from typing import Optional def read_file(path: str, encoding: str = "utf-8") -> Optional[str]: """Read and return the contents of a file. Args: path: Path to the file to read. encoding: File encoding. Defaults to utf-8. Returns: File contents, or None if the file doesn't exist. """ p = Path(path) if not p.exists(): return None return p.read_text(encoding=encoding) class FileCache: """In-memory cache for file contents.""" def __init__(self, root: str): self._root = root self._cache: dict[str, str] = {} def get(self, name: str) -> Optional[str]: if name not in self._cache: self._cache[name] = read_file(os.path.join(self._root, name)) return self._cache[name] ''' config = ProcessConfig( language="python", structure=True, imports=True, docstrings=True, comments=True, diagnostics=True, ) result = process(source, config) # Structure (span lines are zero-indexed; methods live under item.children) for item in result.structure: print(f"{item.kind!s:12} {item.name or '':20} lines {item.span.start_line}-{item.span.end_line}") for child in item.children: print(f" {child.kind!s:10} {child.name or '':20} " f"lines {child.span.start_line}-{child.span.end_line}") # Output: # Function read_file lines 5-19 # Class FileCache lines 21-32 # Method __init__ lines 25-27 # Method get lines 29-32 # Imports for imp in result.imports: names = ", ".join(imp.items) or "*" print(f"from {imp.source} import {names}") # Output: # from os import * # from pathlib import Path # from typing import Optional # Docstrings func = result.structure[0] print(f"\n{func.name} doc comment:\n{func.doc_comment}") # Metrics m = result.metrics print(f"\nLines: {m.total_lines} total, {m.code_lines} code, {m.comment_lines} comments") ``` *** ## Custom Queries [Section titled “Custom Queries”](#custom-queries) Custom query execution helpers are not part of the public API. Use `get_highlights_query`, `get_injections_query`, `get_locals_query`, `get_tags_query`, `get_indents_query`, or `get_folds_query` to retrieve bundled query source, then run host-language tree-sitter query APIs or walk the AST manually when `process()` fields are not enough. # Download Model > How tree-sitter-language-pack downloads, caches, and manages parser binaries on demand. Native tree-sitter-language-pack runtimes fetch parsers on first use and cache them locally. This keeps install sizes small and gives you control over which languages are available. The WebAssembly package is different: it ships a curated static subset of parsers inside the `.wasm` module and does not expose native download/cache helpers. *** ## How It Works [Section titled “How It Works”](#how-it-works) ```mermaid sequenceDiagram participant App participant Core as ts-pack-core participant Cache as Local Cache participant Remote as GitHub Releases App->>Core: get_parser("python") Core->>Cache: is "python" cached? alt cached Cache-->>Core: python.so Core-->>App: Parser else not cached Core->>Remote: GET parsers.json Remote-->>Core: manifest with platform bundle URL Core->>Remote: GET parsers-linux-x86_64.tar.zst Remote-->>Core: bundle bytes Core->>Cache: extract python.so Cache-->>Core: python.so Core-->>App: Parser end ``` The flow in detail: 1. Your code calls `get_parser("python")` (or `get_language`, or `process`). 2. The core checks the local cache directory for the parser binary. 3. If not cached, it fetches `parsers.json` from GitHub releases to find the correct download URL for the current platform. 4. The binary downloads and writes to the cache directory. 5. The process opens the binary via `dlopen` / `LoadLibrary` and resolves the parser symbol. 6. On later calls, the cached binary serves directly — no network access. *** ## Cache Directory [Section titled “Cache Directory”](#cache-directory) Parser libraries live under `/tree-sitter-language-pack/v{version}/libs`, where `{version}` is the package version — so upgrading the package starts from a clean parser set rather than reusing binaries built for an older release. The platform-specific `` base: | Platform | `` base | Resulting parser directory | | -------- | ------------------------------- | --------------------------------------------------------- | | Linux | `$XDG_CACHE_HOME` or `~/.cache` | `~/.cache/tree-sitter-language-pack/v1.14.3/libs` | | macOS | `~/Library/Caches` | `~/Library/Caches/tree-sitter-language-pack/v1.14.3/libs` | | Windows | `%LOCALAPPDATA%` | `%LOCALAPPDATA%\tree-sitter-language-pack\v1.14.3\libs` | You can override it programmatically: * Python Configure language pack with a custom cache directory Python ```python from tree_sitter_language_pack import configure def main() -> None: config = {"cache_dir": "/tmp/tslp_test_cache"} # noqa: S108 configure(config) main() ``` * Node.js Configure language pack with a custom cache directory TypeScript ```typescript import { PackConfig, configure } from "@xberg-io/tree-sitter-language-pack"; function main() { const config: PackConfig = { cacheDir: "/tmp/tslp_test_cache" }; const result = configure(config); } void main(); ``` * Rust Configure language pack with a custom cache directory Rust ```rust use tree_sitter_language_pack::configure; fn main() { let config_json: serde_json::Value = serde_json::from_str(r#"{"cache_dir":"/tmp/tslp_test_cache"}"#).unwrap(); let config = serde_json::from_value(config_json).unwrap(); let _ = configure(&config); } ``` * CLI ```bash ts-pack cache-dir # show current cache dir ``` *** ## Parser Manifest [Section titled “Parser Manifest”](#parser-manifest) The manifest is a JSON file (`parsers.json`) hosted on each GitHub release. It has one bundle per platform (each bundle contains every grammar for that target), plus per-language metadata and group definitions: Platform keys are `{os}-{arch}`, where `os` is `linux`, `macos`, or `windows` and `arch` is the Rust target arch name (`x86_64`, `aarch64`) — except on macOS, where `aarch64` is spelled `arm64`. ```json { "version": "1.14.3", "platforms": { "linux-x86_64": { "url": "https://github.com/.../parsers-linux-x86_64.tar.zst", "sha256": "…", "size": 12345678 }, "linux-aarch64": { "url": "https://github.com/.../parsers-linux-aarch64.tar.zst", "sha256": "…", "size": 12345678 }, "macos-x86_64": { "url": "https://github.com/.../parsers-macos-x86_64.tar.zst", "sha256": "…", "size": 12345678 }, "macos-arm64": { "url": "https://github.com/.../parsers-macos-arm64.tar.zst", "sha256": "…", "size": 12345678 }, "windows-x86_64": { "url": "https://github.com/.../parsers-windows-x86_64.zip", "sha256": "…", "size": 12345678 } }, "languages": { "python": { "group": "all", "size": 524288 }, "rust": { "group": "all", "size": 786432 }, "javascript": { "group": "all", "size": 458752 } }, "groups": { "all": ["python", "rust", "javascript", "..."] } } ``` The manifest caches locally alongside the parser binaries and refreshes on version upgrades. See `ParserManifest` in `crates/ts-pack-core/src/download.rs` for the authoritative schema. `all` is the only group the manifest defines Group names are manifest data, not a constant of any binding. The published manifest emits a single group, `"all"`. Earlier revisions of this page advertised `web`, `systems`, and `scripting`, which the manifest has never contained — `download_group("web")` fails. Call `manifest_groups()` to enumerate the names that actually exist. *** ## Pre-Downloading Parsers [Section titled “Pre-Downloading Parsers”](#pre-downloading-parsers) For production, CI, or offline environments, download parsers explicitly rather than relying on auto-download at runtime. * Python download(\[‘python’, ‘rust’]) returns count >= 2 Python ```python from tree_sitter_language_pack import download def main() -> None: names = ["python", "rust"] result = download(names) print(result) main() ``` * Node.js download(\[‘python’, ‘rust’]) returns count >= 2 TypeScript ```typescript import { download } from "@xberg-io/tree-sitter-language-pack"; function main() { const result = download(["python", "rust"]); console.log(result); } void main(); ``` * Rust download(\[‘python’, ‘rust’]) returns count >= 2 Rust ```rust use tree_sitter_language_pack::download; fn main() { let names_json: serde_json::Value = serde_json::from_str(r#"["python","rust"]"#).unwrap(); let names = serde_json::from_value::>(names_json).unwrap(); let names_refs: Vec<&str> = names.iter().map(String::as_str).collect(); let result = download(&names_refs); println!("{:?}", result); } ``` * CLI ```bash # Download specific parsers ts-pack download python javascript typescript rust # Download all parsers ts-pack download --all # Check what's downloaded ts-pack list --downloaded ``` *** ## Inspecting the Cache [Section titled “Inspecting the Cache”](#inspecting-the-cache) * Python ```python from tree_sitter_language_pack import downloaded_languages, cache_dir, manifest_languages # Languages available locally (no network needed) local = downloaded_languages() print(f"{len(local)} parsers cached at {cache_dir()}") # All languages in the remote manifest remote = manifest_languages() missing = set(remote) - set(local) print(f"{len(missing)} not yet downloaded") ``` * CLI ```bash # Show cache directory path ts-pack cache-dir # List downloaded parsers ts-pack list --downloaded # List all available (remote manifest) ts-pack list --manifest ``` *** ## Cleaning the Cache [Section titled “Cleaning the Cache”](#cleaning-the-cache) * Python ```python from tree_sitter_language_pack import clean_cache clean_cache() # removes all cached parsers ``` * CLI ```bash ts-pack clean # remove all cached parsers (prompts for confirmation) ts-pack clean --force # skip confirmation prompt ``` *** ## Docker and CI [Section titled “Docker and CI”](#docker-and-ci) For containerized deployments, pre-download parsers during the build stage to remove network access at runtime. Dockerfile ```dockerfile FROM python:3.12-slim RUN pip install tree-sitter-language-pack # Pre-download the parsers your application uses RUN python -c "from tree_sitter_language_pack import download; download(['python', 'javascript', 'rust'])" COPY . /app WORKDIR /app CMD ["python", "app.py"] ``` For CI pipelines, cache the parser directory between runs: GitHub Actions ```yaml - name: Cache tree-sitter parsers uses: actions/cache@v4 with: path: ~/.cache/tree-sitter-language-pack key: tslp-parsers-${{ hashFiles('requirements.txt') }} ``` *** ## Configuration File [Section titled “Configuration File”](#configuration-file) For projects that always use the same set of languages, create a `language-pack.toml` in the project root: language-pack.toml ```toml languages = ["python", "javascript", "typescript", "rust", "go"] cache_dir = ".cache/parsers" # optional: project-local cache ``` Then download everything declared: * CLI ```bash ts-pack init --languages python,javascript,typescript,rust,go ts-pack download # downloads all configured languages ``` * Python ```python from tree_sitter_language_pack import init # Reads language-pack.toml from current directory init() ``` See [Configuration](/guides/configuration/) for the full file format and discovery rules. # Host-Native Language Passthrough > How get_language() integrates with native tree-sitter packages across ecosystems. Tree-sitter-language-pack’s `get_language()` function returns the **native tree-sitter `Language` type** for your ecosystem—not a wrapper or opaque handle. This means you can pass the result directly to your parser without translation overhead or intermediate APIs. *** ## Passthrough vs. Opaque Bindings [Section titled “Passthrough vs. Opaque Bindings”](#passthrough-vs-opaque-bindings) ### Passthrough Bindings [Section titled “Passthrough Bindings”](#passthrough-bindings) These 9 bindings return the real `Language` type from the host ecosystem’s tree-sitter package: | Binding | Returns | Host Package | Min Version | | ----------- | ------------------------------------------- | ----------------------------------- | ----------- | | **Python** | `tree_sitter.Language` (PyCapsule) | `tree-sitter` | ≥0.23 | | **Node.js** | `tree-sitter` npm package `Language` | `tree-sitter` | latest | | **Go** | `*tree_sitter.Language` | `go-tree-sitter` | v0.24.0+ | | **Java** | `io.github.treesitter.jtreesitter.Language` | `io.github.tree-sitter:jtreesitter` | 0.26.0+ | | **C#** | `TreeSitter.Language` | `TreeSitter.DotNet` | 1.3.0+ | | **Kotlin** | `io.github.treesitter.ktreesitter.Language` | `io.github.tree-sitter:ktreesitter` | 0.25.0+ | | **Swift** | `SwiftTreeSitter.Language` | `SwiftTreeSitter` (SwiftPM) | 0.25.0+ | | **Zig** | `?*const tree_sitter.Language` | `zig-tree-sitter` | v0.26.0+ | | **C FFI** | `const TSLanguage *` | `tree-sitter` (libtree-sitter) | ABI 14+ | The C FFI surface is the canonical passthrough: `ts_pack_get_language()` returns the bare `const TSLanguage *` that every other C-ABI binding wraps in its host `Language` type. Pass it straight to `ts_parser_set_language()`. The returned pointer is **borrowed** — it points at a static, library-owned grammar, so do not `free` it (there is no `ts_pack_language_free` for it). With a passthrough binding, you use the ecosystem’s native parser without any wrapper: * Python ```python import tree_sitter import tree_sitter_language_pack # get_language returns tree_sitter.Language directly python_lang = tree_sitter_language_pack.get_language("python") # Use it with the native tree-sitter parser parser = tree_sitter.Parser(python_lang) tree = parser.parse(b"def foo(): pass") ``` * Node.js ```typescript import TreeSitter from "tree-sitter"; import * as tslp from "@xberg-io/tree-sitter-language-pack"; // getLanguage returns tree-sitter npm package Language const pythonLang = tslp.getLanguage("python"); // Use it with the native tree-sitter parser const parser = new TreeSitter(); parser.setLanguage(pythonLang); const tree = parser.parse("def foo(): pass"); ``` * Go ```go import ( tree_sitter "github.com/tree-sitter/go-tree-sitter" tspack "github.com/xberg-io/tree-sitter-language-pack/packages/go" ) // GetLanguage returns *tree_sitter.Language directly pythonLang, err := tspack.GetLanguage("python") if err != nil { // get_language can fail (unknown language) return err } // Use it with the native tree-sitter parser parser := tree_sitter.NewParser() parser.SetLanguage(pythonLang) tree := parser.Parse(code, nil) ``` * Java ```java import io.github.treesitter.jtreesitter.Language; import io.github.treesitter.jtreesitter.Parser; import io.xberg.treesitterlanguagepack.TreeSitterLanguagePack; // getLanguage returns jtreesitter Language directly Language pythonLang = TreeSitterLanguagePack.getLanguage("python"); // Use it with the native jtreesitter parser Parser parser = new Parser(); parser.setLanguage(pythonLang); var tree = parser.parse(source); ``` * C ```c #include #include "ts_pack.h" // ts_pack_get_language returns a borrowed const TSLanguage * (NULL on error) const TSLanguage *python_lang = ts_pack_get_language("python"); if (python_lang == NULL) { /* unknown language */ } // Use it directly with the native tree-sitter C API — do NOT free it TSParser *parser = ts_parser_new(); ts_parser_set_language(parser, python_lang); TSTree *tree = ts_parser_parse_string(parser, NULL, "def foo(): pass", 15); ``` ### Opaque-Handle Bindings [Section titled “Opaque-Handle Bindings”](#opaque-handle-bindings) These 5 bindings return an opaque handle specific to this package and do **not** expose a host-native `Language`. Use the package’s own `Parser` / `process()` API instead. | Binding | Why no passthrough | Recommendation | | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------- | | **Ruby** | No maintained Ruby tree-sitter gem that constructs a `Language` from a raw pointer | Use this package’s `Parser` wrapper | | **PHP** | No maintained PHP tree-sitter extension exposing a `Language` from a raw pointer | Use this package’s extension API | | **Elixir** | No maintained Elixir tree-sitter library that ingests a raw `TSLanguage *` | Use this package’s NIF wrapper | | **WASM** | The web-tree-sitter `Language` is loaded from `.wasm` bytes, not a native pointer | Use this package’s JS wrapper | | **Dart** | Built with `flutter_rust_bridge`, which marshals Rust types as Arc-counted opaque proxies and never hands back the raw `const TSLanguage *` the capsule mechanism needs — and there is no maintained Dart tree-sitter package to construct from it | Use the generated `Parser` wrapper | Why Dart is different Python and Node are not C-ABI bindings either, yet they *do* support passthrough — PyO3 and napi-rs let the binding return an arbitrary host object (the upstream `tree_sitter.Language` / the npm `Language`). `flutter_rust_bridge` has no equivalent escape hatch: it auto-wraps every Rust return value in its own `RustOpaque` proxy with an `Arc` lifecycle, so there is no point in the call where a bare `const TSLanguage *` could be handed to a host `Language(pointer)` constructor. Dart passthrough would require both an FRB raw-pointer path and a maintained Dart tree-sitter package — a meaningfully larger effort than the C-ABI bindings. For opaque-handle bindings, use the high-level `process()` function or the package’s `getParser()` method instead: * Ruby ```ruby require "tree_sitter_language_pack" # Use get_parser() to get a pre-configured parser parser = TreeSitterLanguagePack.get_parser("python") # process() takes a ProcessConfig, not a Hash config = TreeSitterLanguagePack::ProcessConfig.new(language: "python") result = TreeSitterLanguagePack.process(source, config) ``` * PHP ```php use Tree\Sitter\Language\Pack\ProcessConfig; use Tree\Sitter\Language\Pack\TreeSitterLanguagePack; // Use getParser() for a pre-configured parser $parser = TreeSitterLanguagePack::getParser("python"); // process() takes a ProcessConfig object, not an array $config = ProcessConfig::from_json(json_encode(["language" => "python"])); $result = TreeSitterLanguagePack::process($source, $config); // TreeSitterLanguagePack delegates to the native extension class // Tree\Sitter\Language\Pack\TreeSitterLanguagePackApi, which you may also call directly: echo TreeSitterLanguagePackApi::languageCount(); ``` *** ## Error Handling [Section titled “Error Handling”](#error-handling) All passthrough bindings require you to handle the possibility that `get_language()` fails (e.g., unknown language name): * Python ```python from tree_sitter_language_pack import LanguageNotFoundError try: lang = get_language("unknown_lang") except LanguageNotFoundError as e: print(f"Language not found: {e}") ``` * Node.js ```typescript try { const lang = tslp.getLanguage("unknown_lang"); } catch (err) { console.error(`Language not found: ${(err as Error).message}`); } ``` * Go ```go lang, err := tspack.GetLanguage("unknown_lang") if err != nil { // Check if it's a language-not-found error return fmt.Errorf("getting language: %w", err) } ``` * Java ```java try { Language lang = TreeSitterLanguagePack.getLanguage("unknown_lang"); } catch (TreeSitterLanguagePackRsException e) { System.err.println("Language not found: " + e.getMessage()); } ``` *** ## Why Passthrough? [Section titled “Why Passthrough?”](#why-passthrough) A passthrough binding returns the ecosystem’s standard tree-sitter `Language`, so: 1. The result works with the existing tree-sitter tooling in that ecosystem — query APIs, tree cursors, and editor integrations — with no wrapper in between. 2. You choose when to upgrade your host tree-sitter package; the grammars are compiled at a backwards-compatible ABI (see below). 3. You can use these 371 grammars alongside custom grammars or other tree-sitter packages in the same parser instance. *** ## ABI Compatibility Window [Section titled “ABI Compatibility Window”](#abi-compatibility-window) The language pack is compiled at tree-sitter **ABI 14**, with 16 exceptions built at ABI 15 because no upstream ABI 14 grammar exists (`abl`, `cpp`, `csharp`, `fsharp`, `fortran`, `gnuplot`, `haxe`, `jai`, `lean`, `perl`, `postgres`, `razor`, `scala`, `slang`, `systemverilog`, `zsh`) — those 16 require a tree-sitter runtime >=0.25. ABI 14 is stable across: * Tree-sitter runtime versions 0.21 through 0.26 * All host package versions listed in the table above This wide compatibility ensures you can use any reasonably recent version of your ecosystem’s tree-sitter package without pinning or rebuilding the language pack. # Contributing > How to contribute to tree-sitter-language-pack — adding languages, fixing bugs, improving bindings, and writing docs. Contributions are welcome: adding a grammar, fixing a bug, improving a binding, or writing documentation. For CI/CD workflow details, see the [CI/CD reference](/contributing/ci/). ## Prerequisites [Section titled “Prerequisites”](#prerequisites) You’ll need the following tools installed: * [Task](https://taskfile.dev/) — the project task runner * Rust stable toolchain via [rustup](https://rustup.rs/) * Python 3.10+ and [uv](https://docs.astral.sh/uv/) * Node.js 18+ and [pnpm](https://pnpm.io/) ## Getting started [Section titled “Getting started”](#getting-started) ```bash # Install Task (macOS) brew install go-task # Clone the repository git clone https://github.com/xberg-io/tree-sitter-language-pack.git cd tree-sitter-language-pack # Install all language dependencies task setup # Build the Rust core task build # Run all tests task test ``` Linux On Debian/Ubuntu, install Task with `apt install go-task` or download from [taskfile.dev](https://taskfile.dev/installation/). ## Common tasks [Section titled “Common tasks”](#common-tasks) ```bash task --list # show all available tasks task build # build Rust core + bindings task test # run all test suites task lint # run all linters (clippy, ruff, oxlint, rubocop, …) task format # auto-format all code task e2e:generate # regenerate e2e test suites from fixtures task e2e:test # run e2e tests task alef:sync # regenerate the alef-managed bindings and docs ``` Run `task --list` to see all available tasks. ## Adding a language [Section titled “Adding a language”](#adding-a-language) The most common contribution is adding a new tree-sitter grammar. ### 1. Find or create a grammar [Section titled “1. Find or create a grammar”](#1-find-or-create-a-grammar) The grammar must: * **Be permissively licensed** — MIT, Apache-2.0, BSD-2-Clause, BSD-3-Clause, ISC, or Unlicense only. We do **not** accept GPL, AGPL, LGPL, MPL, or any copyleft license. This ensures tree-sitter-language-pack can be used freely in any project without imposing license obligations on downstream users. * Have a **public Git repository**. * Produce valid `parser.c` output from `tree-sitter generate`. * Compile cleanly on **Linux, macOS, and Windows**. ### 2. Add the grammar definition [Section titled “2. Add the grammar definition”](#2-add-the-grammar-definition) Edit `sources/language_definitions.json` and add an entry: ```json { "mylang": { "repo": "https://github.com/example/tree-sitter-mylang", "rev": "abc123def456", "branch": "main" } } ``` Always pin to an **exact commit** (`rev`), not a branch tip. This ensures reproducible builds. Available fields: | Field | Required | Description | | ------------ | -------- | ---------------------------------------------------------------------- | | `repo` | Yes | Grammar repository URL | | `rev` | Yes | Exact commit SHA to pin | | `branch` | No | Branch name (used by `scripts/pin_vendors.py` to find latest) | | `directory` | No | Subdirectory within the repo containing the grammar | | `extensions` | No | File extensions that map to this language (e.g. `["rs"]`) | | `ambiguous` | No | Extensions shared with other languages (e.g. `{"h": ["cpp", "objc"]}`) | | `c_symbol` | No | Override for the C symbol name when it differs from the language name | | `generate` | No | Set to `true` to force running `tree-sitter generate` before compiling | ### 3. Build and test [Section titled “3. Build and test”](#3-build-and-test) ```bash # Compile the new parser task build # Run the test suite task test # Verify the parser works end-to-end ts-pack download mylang ts-pack parse example.mylang --language mylang ``` ### 4. Add test fixtures [Section titled “4. Add test fixtures”](#4-add-test-fixtures) Add at least one fixture under `fixtures/`. Fixtures are the single source for both the e2e suites and the documentation snippet corpus — `task e2e:generate` renders each fixture into `docs-site/src/snippets/generated///.md` for all 14 bindings. Do not hand-write snippets; add a fixture instead. A fixture file holds either a **single JSON object** or an **array** of them, grouped into a per-category directory — for example `fixtures/process/python_intel.json`. Only `id` and `description` are required, `additionalProperties` is `false`, the payload goes under `input`, and `assertions` is a list of typed assertion objects, not a map of booleans. See `fixtures/schema.json` for the full assertion-type enum. ```json { "id": "mylang_function_process", "description": "Intel: extract structure from a mylang function definition", "category": "process", "tags": ["intel"], "input": { "source_code": "// example mylang source", "config": { "language": "mylang" } }, "assertions": [ { "type": "equals", "field": "language", "value": "mylang" }, { "type": "count_min", "field": "structure", "value": 1 }, { "type": "equals", "field": "metrics.error_count", "value": 0 } ] } ``` Then regenerate and run e2e tests: ```bash task e2e:generate task e2e:test ``` ### 5. Open a pull request [Section titled “5. Open a pull request”](#5-open-a-pull-request) * **Title:** `feat: add parser` * **Body:** link to the upstream grammar repository, note any quirks or limitations ## Fixing a bug [Section titled “Fixing a bug”](#fixing-a-bug) 1. Check the [issue tracker](https://github.com/xberg-io/tree-sitter-language-pack/issues) — the bug may already be reported. 2. Write a **failing test** that reproduces the issue. 3. Fix the bug in the appropriate crate. 4. Confirm all tests pass with `task test`. 5. Open a PR with a clear description of the root cause and fix. ## Improving bindings [Section titled “Improving bindings”](#improving-bindings) Binding improvements (better error messages, idiomatic APIs, new methods) are welcome. Compiled binding crates live under `crates/` (`ts-pack-core-py`, `ts-pack-core-node`, `ts-pack-core-php`, `ts-pack-core-wasm`, `ts-pack-core-ffi`, `tree-sitter-language-pack-jni`); the host-language packages they feed live under `packages/`. See the [Architecture](/concepts/architecture/) page for the full crate layout. Binding changes must: * **Not add logic that belongs in the Rust core.** Bindings are pure translation layers. * **Have test coverage** in the binding’s native test suite. * **Follow the existing API surface** — most binding surfaces are alef-generated; regenerate them with `task alef:sync` rather than hand-editing generated files. ## Documentation [Section titled “Documentation”](#documentation) Doc fixes and new guides follow the same workflow as code changes: 1. Fork and create a branch. 2. Edit files under `docs-site/src/content/docs/`. Runnable snippets are generated from `fixtures/` into `docs-site/src/snippets/generated//` — change the fixture and rerun `task e2e:generate`, never edit a generated snippet. 3. Preview locally with `pnpm --dir docs-site dev` (the site is Astro / Starlight). 4. Run `task lint` if you touch any scripted checks. 5. Open a pull request. Generated reference pages Everything under `docs-site/src/content/docs/reference/` is alef-generated from the Rust source. Fix the doc comments upstream and run `task alef:sync` — do not edit those pages. Quick edits Use the **Edit** button in the page header to jump directly from any docs page to the matching file on GitHub. ## Code quality [Section titled “Code quality”](#code-quality) The project uses pre-commit hooks managed by [prek](https://github.com/xberg-io/prek): ```bash prek install prek install --hook-type commit-msg ``` Before committing, verify these three commands pass: ```bash task lint # zero warnings required task test # all tests must pass task format # code must be formatted ``` ## Commit style [Section titled “Commit style”](#commit-style) Follow [Conventional Commits](https://www.conventionalcommits.org/): ```text feat: add kotlin parser fix: correct memory layout in Java FFI array freeing chore: update tree-sitter to 0.25 docs: add chunking guide test: add e2e fixtures for ruby ``` Keep commits **small and focused**. Each commit should represent one logical change. ## Pull request checklist [Section titled “Pull request checklist”](#pull-request-checklist) * [ ] `task test` passes * [ ] `task lint` passes (zero warnings) * [ ] New language has at least one fixture under `fixtures/`, with the regenerated snippets under `docs-site/src/snippets/generated/` committed alongside it * [ ] `task e2e:generate && task e2e:test` passes * [ ] `task version:sync` run if any manifest was bumped * [ ] PR description explains the change and links related issues ## Getting help [Section titled “Getting help”](#getting-help) * [GitHub Discussions](https://github.com/xberg-io/tree-sitter-language-pack/discussions) — questions and design conversations * [Discord](https://discord.gg/xt9WY3GnKR) — real-time chat with maintainers * [Issue tracker](https://github.com/xberg-io/tree-sitter-language-pack/issues) — bug reports and feature requests # CI/CD reference > CI/CD workflow reference — what each GitHub Actions workflow does, when it runs, and how publishing works. The project has 16 GitHub Actions workflows in `.github/workflows/`. ## Overview [Section titled “Overview”](#overview) | Workflow | Purpose | Trigger | | --------------------- | --------------------------------------- | ------------------------- | | `ci.yaml` | Main CI — builds and tests all bindings | push/PR to `main` | | `ci-rust.yaml` | Rust core tests and clippy | push/PR to `main` | | `ci-cli.yaml` | CLI-specific tests | push/PR to `main` | | `ci-docker.yaml` | Docker image build and tests | push/PR to `main` | | `ci-e2e.yaml` | Generated cross-language e2e suites | push/PR to `main` | | `ci-dart.yaml` | Dart / Flutter binding tests | push/PR to `main` | | `ci-swift.yaml` | Swift binding tests | push/PR to `main` | | `ci-zig.yaml` | Zig binding tests | push/PR to `main` | | `ci-mobile.yaml` | Kotlin Android binding tests | push/PR to `main` | | `ci-plugin.yaml` | Coding-agent plugin tests | push/PR to `main` | | `docs.yaml` | Build and deploy documentation | push/PR to `main`, manual | | `publish.yaml` | Publish packages to all registries | manual, release | | `publish-docker.yaml` | Build and push Docker image | manual, release | | `publish-pubdev.yaml` | Publish the Dart package to pub.dev | manual, release | | `validate-issues.yml` | Validate issue format | issue opened/edited | | `validate-pr.yml` | Validate PR format | PR opened/edited/synced | *** ## CI workflows [Section titled “CI workflows”](#ci-workflows) ### `ci.yaml` — main CI [Section titled “ci.yaml — main CI”](#ciyaml--main-ci) Runs on push to `main` and pull requests when relevant paths change: `crates/**`, `packages/**`, `e2e/**`, `fixtures/**`, `sources/**`, `scripts/**`, `docs-site/src/snippets/**`, `docs-site/src/content/docs/reference/**`, `.task/**`, `Cargo.toml`, `Cargo.lock`, `Taskfile.yml`, `alef.toml`, `rust-toolchain.toml`, `pyproject.toml`, and the JS workspace manifests. This is the primary workflow that builds and tests all language bindings. ### `ci-cli.yaml` — CLI [Section titled “ci-cli.yaml — CLI”](#ci-cliyaml--cli) Runs on push to `main` and pull requests when CLI or core paths change: `crates/ts-pack-cli/**`, `crates/ts-pack-core/**`, `test_apps/cli/**`. ### `ci-docker.yaml` — Docker [Section titled “ci-docker.yaml — Docker”](#ci-dockeryaml--docker) Runs on push to `main` and pull requests when Docker or core paths change: `docker/**`, `crates/ts-pack-core/**`, `crates/ts-pack-cli/**`. *** ## Docs workflow [Section titled “Docs workflow”](#docs-workflow) `docs.yaml` runs on push and pull requests to `main` when docs files change, and you can also trigger it manually via `workflow_dispatch`. It builds the docs site and deploys it (deploy only on push to `main`). Triggers on changes to: `docs-site/**`, `alef.toml`, and `.github/workflows/docs.yaml`. *** ## Publishing workflows [Section titled “Publishing workflows”](#publishing-workflows) The publish workflows run automatically on a GitHub release event, and you can also trigger them manually via `workflow_dispatch`. ### `publish.yaml` — package releases [Section titled “publish.yaml — package releases”](#publishyaml--package-releases) Takes a release tag (for example `vX.Y.Z`), an optional `dry_run` flag, and an optional `targets` list (comma-separated, defaults to `all`). On a real run, it publishes to all registered package registries simultaneously. ### `publish-docker.yaml` — Docker image [Section titled “publish-docker.yaml — Docker image”](#publish-dockeryaml--docker-image) Takes a release tag and optional `dry_run`. Builds the multi-arch image (amd64 + arm64) using `docker buildx` and pushes to `ghcr.io`. ### `publish-pubdev.yaml` — Dart package [Section titled “publish-pubdev.yaml — Dart package”](#publish-pubdevyaml--dart-package) Publishes the Dart package to pub.dev. Split out from `publish.yaml` because pub.dev uses its own OIDC-based authentication flow. *** ## Validation workflows [Section titled “Validation workflows”](#validation-workflows) ### `validate-issues.yml` [Section titled “validate-issues.yml”](#validate-issuesyml) Validates the format of newly opened or edited issues using a reusable workflow from `xberg-io/actions`. ### `validate-pr.yml` [Section titled “validate-pr.yml”](#validate-pryml) Validates the format of pull requests when opened, edited, or synchronized using a reusable workflow from `xberg-io/actions`. # Xberg Ecosystem > How tree-sitter-language-pack fits into the Xberg family of Rust-core, polyglot-bindings open-source tools. Tree-sitter-language-pack bundles 371 tree-sitter parsers with code intelligence and chunking. It’s part of the Xberg family — a set of open-source tools from the same team, each built on a fast Rust core. Explore the related projects: * [Xberg](https://github.com/xberg-io/xberg) — document intelligence: text, tables, metadata from 101 formats with optional OCR. * [Xberg Enterprise](https://github.com/xberg-io/xberg-enterprise) — managed extraction API with SDKs, dashboards, and observability. * [crawlberg](https://github.com/xberg-io/crawlberg) — web crawling and scraping with HTML→Markdown and headless-Chrome fallback. * [html-to-markdown](https://github.com/xberg-io/html-to-markdown) — fast, lossless HTML→Markdown engine. * [liter-llm](https://github.com/xberg-io/liter-llm) — universal LLM API client with native bindings for 14 languages and 165 providers. * [tree-sitter-language-pack](https://github.com/xberg-io/tree-sitter-language-pack) — tree-sitter grammars and code-intelligence primitives. * [alef](https://github.com/xberg-io/alef) — the polyglot binding generator that produces every per-language binding across the 5 polyglot repos. # Installation > Install tree-sitter-language-pack in Python, Node.js, Rust, Go, Java, C#, Ruby, Elixir, PHP, Dart, Kotlin Android, Swift, Zig, C FFI, WebAssembly, or via the CLI. ## Install using the CLI [Section titled “Install using the CLI”](#install-using-the-cli) The `ts-pack` CLI allows you to manage parsers and run code analysis directly from your terminal. You can use it in CI pipelines, automation scripts, or to explore and experiment with **371 supported languages**. ## CLI [Section titled “CLI”](#cli) * Homebrew ```bash brew trust xberg-io/tap brew install xberg-io/tap/ts-pack ``` * Scoop (Windows) ```powershell scoop bucket add xberg https://github.com/xberg-io/scoop-bucket scoop install ts-pack ``` * Cargo ```bash cargo install ts-pack-cli ``` Or grab the prebuilt binary with [cargo-binstall](https://github.com/cargo-bins/cargo-binstall): ```bash cargo binstall ts-pack-cli ``` Verify ```bash ts-pack --version ts-pack list # language names, then a blank line and an "N language(s)" total ``` `list` shows what is available *locally*, and that depends on how you installed `ts-pack list` reports the grammars this binary can parse right now — those compiled into it, plus any already in your download cache, plus their aliases. That differs by install method: * **Homebrew, Scoop, and `cargo binstall`** fetch the prebuilt release binary, which has all 371 grammars statically linked. `ts-pack list` prints 377 names (371 grammars + 6 aliases), so `ts-pack list | wc -l` is 379 — the 377 names, a blank line, and the `377 language(s)` total. * **`cargo install ts-pack-cli`** compiles from source on your machine with no grammars linked in, so a fresh install prints `0 language(s)` until you run `ts-pack download --all`. `ts-pack list --manifest` lists all 371 downloadable grammars in either case, without touching the cache. ### Run the MCP Server [Section titled “Run the MCP Server”](#run-the-mcp-server) The CLI bundles an MCP server for AI agents: ```bash ts-pack mcp ``` See the [MCP Server guide](/guides/mcp-server/) for integration with Claude Code, Cursor, VS Code, and other tools. *** ## Language Bindings [Section titled “Language Bindings”](#language-bindings) Tree-sitter-language-pack is available for every major ecosystem. All packages share the same version and API surface. What `language_count()` counts `language_count()` returns the parsers **available to this process right now** — grammars compiled into the build, grammars already in the download cache, and their aliases. It is not a constant `371`; that is the number of grammars in the remote manifest. Most published packages (Python, Node.js, Go, Elixir, Zig) compile no grammars in and fetch them on demand, so `language_count()` starts at `0` and grows as you download. The C FFI and C# packages ship with all 371 linked in; the WebAssembly package ships a fixed 31-grammar subset and cannot download more. The verify snippets below confirm the native library loads and links — they are not a grammar count. [Python](#python) [Node.js](#nodejs) [Rust](#rust) [Go](#go) [Java](#java) [C#](#c) [Ruby](#ruby) [Elixir](#elixir) [PHP](#php) [Dart](#dart) [Kotlin Android](#kotlin-android) [Swift](#swift) [Zig](#zig) [C FFI](#c-ffi) [WebAssembly](#webassembly) *** ### Python [Section titled “Python”](#python) Requires Python 3.10+. * pip ```bash pip install tree-sitter-language-pack ``` * uv ```bash uv add tree-sitter-language-pack ``` * poetry ```bash poetry add tree-sitter-language-pack ``` Verify: language\_count returns the number of languages available in the current build/cache Python ```python from tree_sitter_language_pack import language_count def main() -> None: result = language_count() print(result) main() ``` *** ### Node.js [Section titled “Node.js”](#nodejs) Requires Node.js 18+. Pre-built binaries for Linux (x64, arm64), macOS (x64, arm64), and Windows (x64). * npm ```bash npm install @xberg-io/tree-sitter-language-pack ``` * pnpm ```bash pnpm add @xberg-io/tree-sitter-language-pack ``` * Yarn ```bash yarn add @xberg-io/tree-sitter-language-pack ``` Verify: language\_count returns the number of languages available in the current build/cache TypeScript ```typescript import { languageCount } from "@xberg-io/tree-sitter-language-pack"; function main() { const result = languageCount(); console.log(result); } void main(); ``` *** ### Rust [Section titled “Rust”](#rust) Requires Rust 1.85+. * Cargo CLI ```bash cargo add tree-sitter-language-pack ``` * Cargo.toml ```toml [dependencies] tree-sitter-language-pack = "1" ``` Verify: language\_count returns the number of languages available in the current build/cache Rust ```rust use tree_sitter_language_pack::language_count; fn main() { let result = language_count(); println!("{:?}", result); } ``` *** ### Go [Section titled “Go”](#go) Requires Go 1.26+. The binding uses cgo and links against the pre-compiled C FFI library. ```bash go get github.com/xberg-io/tree-sitter-language-pack/packages/go ``` Verify: language\_count returns the number of languages available in the current build/cache Go ```go package main import ( "fmt" tspack "github.com/xberg-io/tree-sitter-language-pack/packages/go" ) func main() { result := tspack.LanguageCount() fmt.Printf("%+v\n", result) } ``` *** ### Java [Section titled “Java”](#java) Requires JDK 25+ (uses Panama FFM API). * Maven ```xml io.xberg.treesitterlanguagepack tree-sitter-language-pack 1.14.3 ``` * Gradle (Kotlin) ```kotlin dependencies { implementation("io.xberg.treesitterlanguagepack:tree-sitter-language-pack:1.14.3") } ``` * Gradle (Groovy) ```groovy dependencies { implementation 'io.xberg.treesitterlanguagepack:tree-sitter-language-pack:1.14.3' } ``` Verify: language\_count returns the number of languages available in the current build/cache Java ```java import io.xberg.treesitterlanguagepack.*; public final class Example { public static void main(String[] args) throws Exception { var result = TreeSitterLanguagePack.languageCount(); System.out.println(result); } } ``` *** ### C\# [Section titled “C#”](#c) Requires .NET 10. ```bash dotnet add package XbergIo.TreeSitterLanguagePack --version 1.14.3 ``` Verify: language\_count returns the number of languages available in the current build/cache C# ```csharp using System; using TreeSitterLanguagePack; var result = TreeSitterLanguagePackConverter.LanguageCount(); Console.WriteLine(result); ``` The NuGet package includes native runtime assets for Windows, Linux, and macOS. *** ### Ruby [Section titled “Ruby”](#ruby) Requires Ruby 3.2+. * gem ```bash gem install tree_sitter_language_pack ``` * Gemfile ```ruby gem "tree_sitter_language_pack", "~> 1.14" ``` ```bash bundle install ``` Verify: language\_count returns the number of languages available in the current build/cache Ruby ```ruby require "tree_sitter_language_pack" result = TreeSitterLanguagePack.language_count() puts result.inspect ``` *** ### Elixir [Section titled “Elixir”](#elixir) Requires Elixir 1.14+ and OTP 25+. * mix.exs ```elixir defp deps do [ {:tree_sitter_language_pack, "~> 1.14"} ] end ``` ```bash mix deps.get ``` Verify: language\_count returns the number of languages available in the current build/cache Elixir ```elixir result = TreeSitterLanguagePack.language_count() IO.inspect(result) ``` *** ### PHP [Section titled “PHP”](#php) Requires PHP 8.2+. This package is a native PHP extension (`type: php-ext`). Install [`mlocati/php-extension-installer`](https://github.com/mlocati/php-extension-installer) first so Composer can download and register the compiled `.so`/`.dll`: ```bash composer require mlocati/php-extension-installer ``` * Composer ```bash composer require xberg-io/tree-sitter-language-pack ``` * composer.json ```json { "require": { "mlocati/php-extension-installer": "^2.0", "xberg-io/tree-sitter-language-pack": "^1.14" } } ``` Verify: language\_count returns the number of languages available in the current build/cache PHP ```php main() async { await RustLib.init(); try { final result = await TreeSitterLanguagePackBridge.languageCount(); stdout.writeln(result); } finally { RustLib.dispose(); } } ``` *** ### Kotlin Android [Section titled “Kotlin Android”](#kotlin-android) Requires Android minSdk 21 and Java 17 bytecode. ```kotlin implementation("io.xberg.tslp.android:tree-sitter-language-pack-android:1.14.3") ``` This is an Android AAR. Kotlin/JVM users should use the Java artifact. Verify: language\_count returns the number of languages available in the current build/cache Kotlin (Android) ```kotlin import io.xberg.tslp.android.* fun main() { val result = TreeSitterLanguagePack.languageCount() println(result) } ``` *** ### Swift [Section titled “Swift”](#swift) Requires Swift 6.0+. ```swift .package( url: "https://github.com/xberg-io/tree-sitter-language-pack", exact: "1.14.3" ) ``` Verify: language\_count returns the number of languages available in the current build/cache Swift ```swift import TreeSitterLanguagePack let result = try TreeSitterLanguagePack.languageCount() print(result) ``` *** ### Zig [Section titled “Zig”](#zig) Requires Zig 0.16+. ```bash zig fetch --save ``` The package name is `tree_sitter_language_pack`. Verify: language\_count returns the number of languages available in the current build/cache Zig ```zig const std = @import("std"); const tree_sitter_language_pack = @import("tree_sitter_language_pack"); pub fn main() !void { const result = tree_sitter_language_pack.language_count(); std.debug.print("{any}\n", .{result}); } ``` *** ### C FFI [Section titled “C FFI”](#c-ffi) Download the shared library and generated C header from GitHub Releases. The C FFI is the stable native contract used by the generated native packages. *** ### WebAssembly [Section titled “WebAssembly”](#webassembly) Use from any JavaScript environment — browsers, Deno, and Cloudflare Workers. * npm ```bash npm install @xberg-io/tree-sitter-language-pack-wasm ``` * CDN (browser) ```html ``` * Deno ```typescript import { availableLanguages, languageCount } from "npm:@xberg-io/tree-sitter-language-pack-wasm"; {/* Verify snippets come from the alef-generated corpus (fixture `registry_language_count`). Node.js reuses the TypeScript rendering; there is no generated corpus for the CLI. */} console.log(languageCount(), availableLanguages()); ``` Verify: language\_count returns the number of languages available in the current build/cache WebAssembly ```typescript import { languageCount } from "@xberg-io/tree-sitter-language-pack-wasm"; function main() { const result = languageCount(); console.log(result); } void main(); ``` The WASM package is a static curated subset of parsers compiled into the module. It does not expose the native download/cache helpers. *** ## Next Steps [Section titled “Next Steps”](#next-steps) * [Quick Start](/getting-started/quickstart/) — parse your first file in 5 minutes * [Download parsers](/getting-started/quickstart/#2-download-parsers) — pre-download grammars for production, CI, or offline use * [Download model](/concepts/download-model/) — understand how parser caching works * [Languages](/languages/) — full list of 371 supported languages # Quick Start > Parse your first file with tree-sitter-language-pack in under 5 minutes. This guide walks you from install to parsing, code intelligence, and LLM chunking. *** ## 1. Install [Section titled “1. Install”](#1-install) * Python ```bash pip install tree-sitter-language-pack ``` * Node.js ```bash npm install @xberg-io/tree-sitter-language-pack ``` * Rust ```bash cargo add tree-sitter-language-pack ``` * CLI ```bash brew trust xberg-io/tap brew install xberg-io/tap/ts-pack ``` On Windows: ```powershell scoop bucket add xberg https://github.com/xberg-io/scoop-bucket scoop install ts-pack ``` Other ecosystems Go, Java, C#, Ruby, Elixir, PHP, Dart, Kotlin Android, Swift, Zig, C FFI, and WebAssembly are also supported. See [Installation](/getting-started/installation/) for the full list. *** ## 2. Download Parsers [Section titled “2. Download Parsers”](#2-download-parsers) Parsers download automatically on first use. For **production, CI, Docker, or offline** environments, pre-download them. ### Specific languages [Section titled “Specific languages”](#specific-languages) * CLI CLI ```bash # Download specific languages ts-pack download python javascript rust go # Download all available languages ts-pack download --all # Download a language group (the manifest currently defines only "all") ts-pack download --groups all # Fresh download (clear cache first) ts-pack download --fresh python # Check what's cached ts-pack list --downloaded ``` * Python Download a single language parser and verify count Python ```python from tree_sitter_language_pack import download def main() -> None: names = ["python"] result = download(names) print(result) main() ``` * Node.js Download a single language parser and verify count TypeScript ```typescript import { download } from "@xberg-io/tree-sitter-language-pack"; function main() { const result = download(["python"]); console.log(result); } void main(); ``` * Ruby Download a single language parser and verify count Ruby ```ruby require "tree_sitter_language_pack" result = TreeSitterLanguagePack.download(['python']) puts result.inspect ``` * PHP Download a single language parser and verify count PHP ```php () { JsonSerializer.Deserialize("\"python\"", ConfigOptions)! }); Console.WriteLine(result); ``` * Elixir Download a single language parser and verify count Elixir ```elixir result = TreeSitterLanguagePack.download(["python"]) IO.inspect(result) ``` * Dart Download a single language parser and verify count Dart ```dart import 'dart:io'; import 'package:tree_sitter_language_pack/tree_sitter_language_pack.dart'; import 'package:tree_sitter_language_pack/src/tree_sitter_language_pack_bridge_generated/frb_generated.dart' show RustLib; Future main() async { await RustLib.init(); try { final result = await TreeSitterLanguagePackBridge.download(['python']); stdout.writeln(result); } finally { RustLib.dispose(); } } ``` * Swift Download a single language parser and verify count Swift ```swift import TreeSitterLanguagePack let result = try TreeSitterLanguagePack.download(names: ["python"]) print(result) ``` * Zig Download a single language parser and verify count Zig ```zig const std = @import("std"); const tree_sitter_language_pack = @import("tree_sitter_language_pack"); pub fn main() !void { const result = try tree_sitter_language_pack.download("[\"python\"]"); std.debug.print("{any}\n", .{result}); } ``` * Kotlin (Android) prefetch(\[‘python’]) downloads and loads parser Kotlin (Android) ```kotlin import io.xberg.tslp.android.* fun main() { TreeSitterLanguagePack.prefetch(listOf("python")) } ``` * WebAssembly prefetch(\[‘python’]) downloads and loads parser WebAssembly ```typescript import { prefetch } from "@xberg-io/tree-sitter-language-pack-wasm"; function main() { const result = prefetch(["python"]); } void main(); ``` * Rust Download a single language parser and verify count Rust ```rust use tree_sitter_language_pack::download; fn main() { let names_json: serde_json::Value = serde_json::from_str(r#"["python"]"#).unwrap(); let names = serde_json::from_value::>(names_json).unwrap(); let names_refs: Vec<&str> = names.iter().map(String::as_str).collect(); let result = download(&names_refs); println!("{:?}", result); } ``` ### All 371 languages [Section titled “All 371 languages”](#all-371-languages) * CLI ```bash ts-pack download --all ``` * Python ```python from tree_sitter_language_pack import download_all download_all() ``` * Node.js ```typescript import { downloadAll } from "@xberg-io/tree-sitter-language-pack"; downloadAll(); ``` * Rust ```rust use tree_sitter_language_pack::download_all; download_all()?; ``` ### By language group [Section titled “By language group”](#by-language-group) Group names are manifest data, not a compile-time constant. The published manifest currently defines exactly one group, `"all"` — there is no `web`, `data`, or `systems` group, and passing one fails. Enumerate the real names with `manifest_groups()` before calling `download_group()`. * Python ```python from tree_sitter_language_pack import download_group, manifest_groups for group in manifest_groups(): print(group) # currently prints just: all download_group("all") ``` * Rust ```rust use tree_sitter_language_pack::{download_group, manifest_groups}; let group = manifest_groups()? .into_iter() .next() .expect("manifest defines no groups"); let count = download_group(&group)?; println!("{count} languages available"); ``` ### Docker and CI [Section titled “Docker and CI”](#docker-and-ci) Pre-download parsers during your build to avoid runtime network calls: Dockerfile ```dockerfile FROM python:3.12-slim RUN pip install tree-sitter-language-pack # Pre-download at build time — no network needed at runtime RUN python -c "from tree_sitter_language_pack import download_all; download_all()" ``` GitHub Actions ```yaml - name: Install and pre-download parsers run: | pip install tree-sitter-language-pack python -c "from tree_sitter_language_pack import download; download(['python', 'javascript', 'rust'])" ``` ### Configuration file [Section titled “Configuration file”](#configuration-file) Declare which languages your project needs in a `language-pack.toml`: language-pack.toml ```toml languages = ["python", "javascript", "rust", "go"] # groups = ["all"] # only names returned by manifest_groups() are accepted # cache_dir = "/tmp/parsers" ``` Then download everything declared in the config: * CLI ```bash # Reads language-pack.toml automatically ts-pack download ``` * Python ```python from tree_sitter_language_pack import init # Reads language-pack.toml from current directory init() ``` Cache location Parsers cache to `/tree-sitter-language-pack/v{version}/libs` — where `` is `~/.cache` on Linux, `~/Library/Caches` on macOS, and `%LOCALAPPDATA%` on Windows. Override with `cache_dir` in `language-pack.toml` or the programmatic API. See [Download Model](/concepts/download-model/) for full details. *** ## 3. Parse Code [Section titled “3. Parse Code”](#3-parse-code) Run the parser over a source string. `process()` parses the source and returns the result; if the language is not cached yet it is downloaded on this first call. * CLI CLI ```bash # Download parsers ts-pack download python javascript rust # Parse a file ts-pack parse main.py --format json # Run code intelligence ts-pack process src/app.py --all # List available languages ts-pack list --manifest ``` * Python Parse a Python function definition and assert node type Python ```python from tree_sitter_language_pack import process def main() -> None: source = "def hello(): pass" config = {"language": "python"} result = process(source, config) print(result) main() ``` * Node.js Parse a Python function definition and assert node type TypeScript ```typescript import { ProcessConfig, process } from "@xberg-io/tree-sitter-language-pack"; function main() { const config: ProcessConfig = { language: "python" }; const result = process("def hello(): pass", config); console.log(result); } void main(); ``` * Ruby Parse a Python function definition and assert node type Ruby ```ruby require "tree_sitter_language_pack" result = TreeSitterLanguagePack.process('def hello(): pass', { 'language' => 'python' }) puts result.inspect ``` * PHP Parse a Python function definition and assert node type PHP ```php "python"])); $result = TreeSitterLanguagePack::process("def hello(): pass", $config); var_dump($result); ``` * Go Parse a Python function definition and assert node type Go ```go package main import ( "fmt" tspack "github.com/xberg-io/tree-sitter-language-pack/packages/go" ) func main() { config := tspack.ProcessConfig{ Language: `python`, } result, err := tspack.Process(`def hello(): pass`, config) if err != nil { panic(err) } fmt.Printf("%+v\n", result) } ``` * Java Parse a Python function definition and assert node type Java ```java import io.xberg.treesitterlanguagepack.*; public final class Example { public static void main(String[] args) throws Exception { var configJson = "{\"language\":\"python\"}"; var config = JsonUtil.fromJson(configJson, ProcessConfig.class); var result = TreeSitterLanguagePack.process("def hello(): pass", config); System.out.println(result); } } ``` * C# Parse a Python function definition and assert node type C# ```csharp using System; using TreeSitterLanguagePack; var result = TreeSitterLanguagePackConverter.Process("def hello(): pass", new ProcessConfig { Language = "python" }); Console.WriteLine(result); ``` * Elixir Parse a Python function definition and assert node type Elixir ```elixir config_value = %TreeSitterLanguagePack.ProcessConfig{language: "python"} result = TreeSitterLanguagePack.process("def hello(): pass", config_value) IO.inspect(result) ``` * Dart Parse a Python function definition and assert node type Dart ```dart import 'dart:io'; import 'package:tree_sitter_language_pack/tree_sitter_language_pack.dart'; import 'package:tree_sitter_language_pack/src/tree_sitter_language_pack_bridge_generated/frb_generated.dart' show RustLib; Future main() async { await RustLib.init(); try { final config = await createProcessConfigFromJson(json: '{"language":"python"}'); final result = await TreeSitterLanguagePackBridge.process('def hello(): pass', config: config); stdout.writeln(result); } finally { RustLib.dispose(); } } ``` * Swift Parse a Python function definition and assert node type Swift ```swift import TreeSitterLanguagePack let configObj = try TreeSitterLanguagePack.processConfigFromJson("{\"language\":\"python\"}") let result = try TreeSitterLanguagePack.process(source: "def hello(): pass", config: configObj) print(result) ``` * Zig Parse a Python function definition and assert node type Zig ```zig const std = @import("std"); const tree_sitter_language_pack = @import("tree_sitter_language_pack"); pub fn main() !void { const _result_json = try tree_sitter_language_pack.process("def hello(): pass", "{\"language\":\"python\"}"); defer std.heap.c_allocator.free(_result_json); std.debug.print("{s}\n", .{_result_json}); } ``` * Kotlin (Android) Parse a Python function definition and assert node type Kotlin (Android) ```kotlin import io.xberg.tslp.android.* import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper fun main() { val mapper = jacksonObjectMapper() val config = mapper.readValue("{\"language\":\"python\"}", ProcessConfig::class.java) val result = TreeSitterLanguagePack.process("def hello(): pass", config) println(result) } ``` * WebAssembly Parse a Python function definition and assert node type WebAssembly ```typescript import { WasmProcessConfig, process } from "@xberg-io/tree-sitter-language-pack-wasm"; function main() { const config: WasmProcessConfig = (() => { const _u0 = WasmProcessConfig.default(); _u0.language = "python"; return _u0; })(); const result = process("def hello(): pass", config); console.log(result); } void main(); ``` * Rust Parse a Python function definition and assert node type Rust ```rust use tree_sitter_language_pack::process; fn main() { let source = r#"def hello(): pass"#; let config_json: serde_json::Value = serde_json::from_str(r#"{"language":"python"}"#).unwrap(); let config = serde_json::from_value(config_json).unwrap(); let result = process(source, &config); println!("{:?}", result); } ``` *** ## 4. Extract Code Intelligence [Section titled “4. Extract Code Intelligence”](#4-extract-code-intelligence) Go beyond the raw syntax tree. Extract functions, classes, imports, docstrings, and more with `process`. * CLI CLI ```bash # Parse and show S-expression ts-pack parse main.py --language python # Parse as JSON echo "fn main() {}" | ts-pack parse - --language rust --format json # Full code intelligence ts-pack process src/app.py --language python --all # Structure + imports only ts-pack process src/app.py --structure --imports ``` * Python Intel: process with all features enabled Python ```python from tree_sitter_language_pack import process def main() -> None: source = "# A comment\ndef greet(name):\n \"\"\"Say hello.\"\"\"\n return f'Hi {name}'\n\nimport os\n" config = {"language": "python"} result = process(source, config) print(result.language) print(result.structure) print(result.structure[0].kind) print(result.imports) print(result.metrics.total_lines) print(result.metrics.error_count) main() ``` * Node.js Intel: process with all features enabled TypeScript ```typescript import { ProcessConfig, process } from "@xberg-io/tree-sitter-language-pack"; function main() { const config: ProcessConfig = { language: "python" }; const result = process("# A comment\ndef greet(name):\n \"\"\"Say hello.\"\"\"\n return f'Hi {name}'\n\nimport os\n", config); console.log(result.language); console.log(result.structure); console.log(result.structure?.[0]?.kind); console.log(result.imports); console.log(result.metrics?.totalLines); console.log(result.metrics?.errorCount); } void main(); ``` * Ruby Intel: process with all features enabled Ruby ```ruby require "tree_sitter_language_pack" result = TreeSitterLanguagePack.process("\# A comment\ndef greet(name):\n \"\"\"Say hello.\"\"\"\n return f'Hi {name}'\n\nimport os\n", { 'language' => 'python' }) puts result.language.inspect puts result.structure.inspect puts result.structure[0].kind.inspect puts result.imports.inspect puts result.metrics.total_lines.inspect puts result.metrics.error_count.inspect ``` * PHP Intel: process with all features enabled PHP ```php "python"])); $result = TreeSitterLanguagePack::process("# A comment\ndef greet(name):\n \"\"\"Say hello.\"\"\"\n return f'Hi {name}'\n\nimport os\n", $config); var_dump($result->language); var_dump($result->getStructure()); var_dump($result->getStructure()[0]->kind); var_dump($result->getImports()); var_dump($result->getMetrics()->totalLines); var_dump($result->getMetrics()->errorCount); ``` * Go Intel: process with all features enabled Go ```go package main import ( "fmt" tspack "github.com/xberg-io/tree-sitter-language-pack/packages/go" ) func main() { config := tspack.ProcessConfig{ Language: `python`, } result, err := tspack.Process(`# A comment def greet(name): """Say hello.""" return f'Hi {name}' import os `, config) if err != nil { panic(err) } fmt.Printf("%+v\n", result.Language) fmt.Printf("%+v\n", result.Structure) fmt.Printf("%+v\n", result.Structure[0].Kind) fmt.Printf("%+v\n", result.Imports) fmt.Printf("%+v\n", result.Metrics.TotalLines) fmt.Printf("%+v\n", result.Metrics.ErrorCount) } ``` * Java Intel: process with all features enabled Java ```java import io.xberg.treesitterlanguagepack.*; public final class Example { public static void main(String[] args) throws Exception { var configJson = "{\"language\":\"python\"}"; var config = JsonUtil.fromJson(configJson, ProcessConfig.class); var result = TreeSitterLanguagePack.process("# A comment\ndef greet(name):\n \"\"\"Say hello.\"\"\"\n return f'Hi {name}'\n\nimport os\n", config); System.out.println(result.language()); System.out.println(result.structure()); System.out.println(result.structure().get(0).kind()); System.out.println(result.imports()); System.out.println(result.metrics().totalLines()); System.out.println(result.metrics().errorCount()); } } ``` * C# Intel: process with all features enabled C# ```csharp using System; using TreeSitterLanguagePack; var result = TreeSitterLanguagePackConverter.Process("# A comment\ndef greet(name):\n \"\"\"Say hello.\"\"\"\n return f'Hi {name}'\n\nimport os\n", new ProcessConfig { Language = "python" }); Console.WriteLine(result.Language); Console.WriteLine(result.Structure); Console.WriteLine(result.Structure[0].Kind); Console.WriteLine(result.Imports); Console.WriteLine(result.Metrics.TotalLines); Console.WriteLine(result.Metrics.ErrorCount); ``` * Elixir Intel: process with all features enabled Elixir ```elixir config_value = %TreeSitterLanguagePack.ProcessConfig{language: "python"} result = TreeSitterLanguagePack.process("\# A comment\ndef greet(name):\n \"\"\"Say hello.\"\"\"\n return f'Hi {name}'\n\nimport os\n", config_value) IO.inspect(result.language) IO.inspect(result.structure) IO.inspect(Enum.at(result.structure, 0).kind) IO.inspect(result.imports) IO.inspect(result.metrics.total_lines) IO.inspect(result.metrics.error_count) ``` * Dart Intel: process with all features enabled Dart ```dart import 'dart:io'; import 'package:tree_sitter_language_pack/tree_sitter_language_pack.dart'; import 'package:tree_sitter_language_pack/src/tree_sitter_language_pack_bridge_generated/frb_generated.dart' show RustLib; Future main() async { await RustLib.init(); try { final config = await createProcessConfigFromJson(json: '{"language":"python"}'); final result = await TreeSitterLanguagePackBridge.process('# A comment\ndef greet(name):\n """Say hello."""\n return f\'Hi {name}\'\n\nimport os\n', config: config); stdout.writeln(result.language); stdout.writeln(result.structure); stdout.writeln(result.structure[0].kind); stdout.writeln(result.imports); stdout.writeln(result.metrics.totalLines); stdout.writeln(result.metrics.errorCount); } finally { RustLib.dispose(); } } ``` * Swift Intel: process with all features enabled Swift ```swift import TreeSitterLanguagePack let configObj = try TreeSitterLanguagePack.processConfigFromJson("{\"language\":\"python\"}") let result = try TreeSitterLanguagePack.process(source: "# A comment\ndef greet(name):\n \"\"\"Say hello.\"\"\"\n return f'Hi {name}'\n\nimport os\n", config: configObj) debugPrint(result.language()) debugPrint(result.structure()) debugPrint(result.structure()[0].kind()) debugPrint(result.imports()) debugPrint(result.metrics().totalLines()) debugPrint(result.metrics().errorCount()) ``` * Zig Intel: process with all features enabled Zig ```zig const std = @import("std"); const tree_sitter_language_pack = @import("tree_sitter_language_pack"); pub fn main() !void { const _result_json = try tree_sitter_language_pack.process("# A comment\ndef greet(name):\n \"\"\"Say hello.\"\"\"\n return f'Hi {name}'\n\nimport os\n", "{\"language\":\"python\"}"); defer std.heap.c_allocator.free(_result_json); std.debug.print("{s}\n", .{_result_json}); } ``` * Kotlin (Android) Intel: process with all features enabled Kotlin (Android) ```kotlin import io.xberg.tslp.android.* import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper fun main() { val mapper = jacksonObjectMapper() val config = mapper.readValue("{\"language\":\"python\"}", ProcessConfig::class.java) val result = TreeSitterLanguagePack.process("# A comment\ndef greet(name):\n \"\"\"Say hello.\"\"\"\n return f'Hi {name}'\n\nimport os\n", config) println(result.language) println(result.structure) println(result.structure.first().kind) println(result.imports) println(result.metrics.totalLines) println(result.metrics.errorCount) } ``` * WebAssembly Intel: process with all features enabled WebAssembly ```typescript import { WasmProcessConfig, process } from "@xberg-io/tree-sitter-language-pack-wasm"; function main() { const config: WasmProcessConfig = (() => { const _u0 = WasmProcessConfig.default(); _u0.language = "python"; return _u0; })(); const result = process("# A comment\ndef greet(name):\n \"\"\"Say hello.\"\"\"\n return f'Hi {name}'\n\nimport os\n", config); console.log(result.language); console.log(result.structure); console.log(result.structure[0].kind); console.log(result.imports); console.log(result.metrics.totalLines); console.log(result.metrics.errorCount); } void main(); ``` * Rust Intel: process with all features enabled Rust ```rust use tree_sitter_language_pack::process; fn main() { let source = r#"# A comment def greet(name): """Say hello.""" return f'Hi {name}' import os "#; let config_json: serde_json::Value = serde_json::from_str(r#"{"language":"python"}"#).unwrap(); let config = serde_json::from_value(config_json).unwrap(); let result = process(source, &config).expect("call failed"); println!("{:?}", result.language); println!("{:?}", result.structure); println!("{:?}", result.structure[0].kind); println!("{:?}", result.imports); println!("{:?}", result.metrics.total_lines); println!("{:?}", result.metrics.error_count); } ``` *** ## 5. Inspect Query Sources [Section titled “5. Inspect Query Sources”](#5-inspect-query-sources) `process()` covers the built-in intelligence fields. There is no public `extract()` helper for arbitrary query execution. For custom analysis, fetch bundled query source with helpers such as `get_tags_query()`, then run tree-sitter query APIs yourself or walk the AST manually. * Python ```python from tree_sitter_language_pack import get_tags_query tags_query = get_tags_query("python") if tags_query is not None: print(tags_query.splitlines()[0]) ``` * Rust ```rust use tree_sitter_language_pack::{get_parser, get_tags_query}; let query_source = get_tags_query("rust"); let mut parser = get_parser("rust")?; let tree = parser.parse("fn main() {}").ok_or("failed to parse")?; println!("{}", tree.root_node().kind()); ``` *** ## 6. Chunk for LLMs [Section titled “6. Chunk for LLMs”](#6-chunk-for-llms) Split code at natural boundaries so language models receive coherent, complete units which is ideal for embedding pipelines and context windows. * Python ```python from tree_sitter_language_pack import process, ProcessConfig with open("large_module.py") as f: source = f.read() config = ProcessConfig( language="python", chunk_max_size=1500, # max bytes per chunk structure=True, ) result = process(source, config) for i, chunk in enumerate(result.chunks): print(f"Chunk {i}: lines {chunk.start_line}-{chunk.end_line} " f"({chunk.end_byte - chunk.start_byte} bytes)") ``` * Node.js ```typescript import { process } from "@xberg-io/tree-sitter-language-pack"; import { readFileSync } from "fs"; const source = readFileSync("large_module.ts", "utf8"); const result = process(source, { language: "typescript", chunkMaxSize: 1500, structure: true, }); result.chunks.forEach((chunk, i) => { console.log(`Chunk ${i}: lines ${chunk.startLine}-${chunk.endLine} (${chunk.endByte - chunk.startByte} bytes)`); }); ``` * CLI ```bash # Chunk a file for LLM ingestion ts-pack process large_module.py --chunk-size 1500 \ | jq '.chunks[] | {start: .start_line, end: .end_line, bytes: (.end_byte - .start_byte)}' ``` *** You now have the full workflow. You can now install, download, parse, extract intelligence, inspect query sources, and chunk for LLMs. Go further with the following guides: * [Parsing guide](/guides/parsing/) — syntax trees, error handling, and incremental parsing * [Configuration](/guides/configuration/) — `language-pack.toml` and advanced options * [API Reference](/reference/api-python/) — full API docs for every binding # AI Coding Assistants > Install the tree-sitter-language-pack plugin into Claude Code, Codex, Cursor, Gemini, Factory Droid, GitHub Copilot, or opencode. Give your coding agent structural understanding of any codebase — parse and extract code intelligence from 371 languages without leaving the chat. ## What this plugin does [Section titled “What this plugin does”](#what-this-plugin-does) The plugin drops the tree-sitter-language-pack agent skills straight into your coding assistant. Once installed, the agent can: * Parse a file in any of 371 languages and reason over its syntax tree. * Pull out functions, classes, imports, exports, and symbols on request. * Detect a file’s language, list supported languages, and manage the local parser cache. Under the hood it registers the `tree-sitter-language-pack` MCP server for you, so there is nothing to configure by hand. The plugin ships from this repository’s own marketplace, [`xberg-io/tree-sitter-language-pack`](https://github.com/xberg-io/tree-sitter-language-pack), where you can also see its version history and source. If you prefer manual MCP registration over the plugin, the CLI exposes the same server directly. See the [MCP Server guide](/guides/mcp-server/) for stdio and HTTP transport setup with any compatible IDE. ## Installing [Section titled “Installing”](#installing) Pick your harness below. **Claude Code** ```text /plugin marketplace add xberg-io/tree-sitter-language-pack /plugin install tree-sitter-language-pack@tree-sitter-language-pack ``` **Codex CLI** ```text /plugins add https://github.com/xberg-io/tree-sitter-language-pack ``` Then search for `tree-sitter-language-pack` and select **Install Plugin**. **Cursor** Settings → Plugins → Add from URL → `https://github.com/xberg-io/tree-sitter-language-pack`, then select **tree-sitter-language-pack**. **Gemini CLI** ```text gemini extensions install https://github.com/xberg-io/tree-sitter-language-pack ``` **Factory Droid** ```text droid plugin marketplace add https://github.com/xberg-io/tree-sitter-language-pack droid plugin install tree-sitter-language-pack@tree-sitter-language-pack ``` **GitHub Copilot CLI** ```text copilot plugin marketplace add https://github.com/xberg-io/tree-sitter-language-pack copilot plugin install tree-sitter-language-pack@tree-sitter-language-pack ``` **opencode** Add the package to `opencode.json`: ```json { "$schema": "https://opencode.ai/config.json", "plugin": ["@xberg-io/opencode-tree-sitter-language-pack"] } ``` **Hermes** Install the Hermes plugin from PyPI — Hermes auto-discovers it via entry points, so no extra configuration is needed: ```bash pip install tree-sitter-language-pack-hermes-plugin ``` # Building from source > How to build tree-sitter-language-pack from source, configure feature flags, and compile parsers statically. This guide covers building the Rust core from source — useful if you need static linking, a custom parser subset, or want to contribute to the library itself. ## Prerequisites [Section titled “Prerequisites”](#prerequisites) * Rust toolchain (see `rust-toolchain.toml` in the repository root for the pinned version) * Python 3 (for the vendor scripts) * A C compiler (`gcc` or `clang`) — required by `build.rs` to compile parser grammars * The [Task](https://taskfile.dev) runner Clone the repository: ```bash git clone https://github.com/xberg-io/tree-sitter-language-pack cd tree-sitter-language-pack ``` ## Workspace layout [Section titled “Workspace layout”](#workspace-layout) The Cargo workspace contains the following crates: | Crate | Purpose | | -------------------------- | --------------------------------------------- | | `crates/ts-pack-core` | Core Rust library (parsers, download, config) | | `crates/ts-pack-cli` | `ts-pack` CLI binary | | `crates/ts-pack-core-py` | Python bindings (PyO3/maturin) | | `crates/ts-pack-core-node` | Node.js bindings (NAPI-RS) | | `crates/ts-pack-core-php` | PHP extension (ext-php-rs) | | `crates/ts-pack-core-wasm` | WebAssembly bindings (wasm-bindgen) | | `crates/ts-pack-core-ffi` | C-compatible FFI library (cbindgen) | Language-specific packages live under `packages/`: `python/`, `ruby/`, `elixir/`, `php/`, `go/`, `java/`, `csharp/`, `dart/`, `kotlin-android/`, `swift/`, and `zig/`. The Node.js and WebAssembly packages are published straight from `crates/ts-pack-core-node` and `crates/ts-pack-core-wasm` and have no `packages/` directory. ## Cargo features [Section titled “Cargo features”](#cargo-features) The core library (`tree-sitter-language-pack`) has four features: | Feature | Default | What it enables | | ----------------- | ------- | ---------------------------------------------------------------- | | `dynamic-loading` | Yes | Load parser `.so`/`.dylib`/`.dll` files at runtime | | `download` | Yes | Download parsers from GitHub releases; implies `dynamic-loading` | | `serde` | No | `Serialize`/`Deserialize` on public types | | `config` | No | Read `language-pack.toml` config files; enables `dep:serde` | To use the library without the download machinery (for example in a Wasm target or with statically compiled parsers): ```toml [dependencies] tree-sitter-language-pack = { version = "...", default-features = false } ``` ## Build-time environment variables [Section titled “Build-time environment variables”](#build-time-environment-variables) `build.rs` reads these variables at compile time, not at runtime. ### `TSLP_LANGUAGES` [Section titled “TSLP\_LANGUAGES”](#tslp_languages) Comma-separated list of languages to compile statically into the binary. When set, `build.rs` compiles those parser grammars from source and links them in. ```bash TSLP_LANGUAGES=python,rust,javascript cargo build ``` When not set (the default), no parsers get compiled statically. The library downloads them at runtime using the `download` feature. Names must be alphanumeric or underscore and must exist in `sources/language_definitions.json`. Unknown names produce a build warning. ### `TSLP_LINK_MODE` [Section titled “TSLP\_LINK\_MODE”](#tslp_link_mode) Controls how statically-selected parsers link. Requires `TSLP_LANGUAGES`. | Value | Effect | | ------------------- | ---------------------------------------------------------------------- | | `dynamic` (default) | Compile parsers into `.so`/`.dylib`/`.dll` files, load them at runtime | | `static` | Link parsers directly into the binary | | `both` | Produce both static and dynamic variants | `wasm32` targets always use `static`, regardless of this setting. ### `TSLP_LINK_MODE=static` example [Section titled “TSLP\_LINK\_MODE=static example”](#tslp_link_modestatic-example) To produce a single self-contained binary: ```bash TSLP_LANGUAGES=python,rust,javascript TSLP_LINK_MODE=static cargo build --release ``` ### `PROJECT_ROOT` [Section titled “PROJECT\_ROOT”](#project_root) Override the directory `build.rs` searches for `sources/language_definitions.json`. `build.rs` walks up the directory tree to find it automatically; this variable is useful for unusual build setups. ### `WASI_SYSROOT` [Section titled “WASI\_SYSROOT”](#wasi_sysroot) Path to the WASI sysroot when cross-compiling for `wasm32-wasi`. Used by `build.rs` when targeting that architecture. ### Grammar-source and wasm gates [Section titled “Grammar-source and wasm gates”](#grammar-source-and-wasm-gates) | Variable | Effect | | ---------------------------- | ----------------------------------------------------------------------------------------------- | | `TSLP_OFFLINE` | Any non-empty, non-`0` value stops `build.rs` from downloading the parser-source bundle | | `TSLP_SOURCE_BUNDLE_URL` | Override the `parser-sources-{version}.tar.zst` release-asset URL | | `TSLP_ALLOW_FAILED_GRAMMARS` | `1` downgrades grammar compile failures from a hard error to a warning — local debugging only | | `TSLP_WASM_MAX_PARSER_BYTES` | `wasm32` only: `parser.c` size gate in bytes; `0` disables the gate | | `TSLP_WASM_SKIP_GRAMMARS` | `wasm32` only: comma-separated grammars to skip, replacing the default list (empty disables it) | `TSLP_MSVC_PATCH` is **not** an environment variable — it is a marker comment `build.rs` writes into sources it patches for MSVC, so patched files are recognised on later builds. ## How build.rs works [Section titled “How build.rs works”](#how-buildrs-works) `build.rs` (in `crates/ts-pack-core/`) runs every time environment variables or source files change. It does these steps: 1. **Reads `sources/language_definitions.json`** — 371 language entries, each specifying the grammar repository, revision, file extensions, and optional C symbol overrides. 2. **Compiles selected parsers** — when `TSLP_LANGUAGES` has a value, it invokes the system C compiler on each `parsers//src/parser.c`. The output format (static archive or shared library) follows from `TSLP_LINK_MODE`. 3. **Generates Rust source files** written to `OUT_DIR`: * `registry_generated.rs` — the language registry (name → parser function) * `extensions_generated.rs` — file extension to language name mapping * `ambiguities_generated.rs` — ambiguous extension lookup table * Query files for all six bundled query kinds: `highlights.scm`, `injections.scm`, `locals.scm`, `tags.scm`, `indents.scm`, and `folds.scm` The build embeds these generated files via `include!()` macros in `src/registry.rs` and `src/extensions.rs`. ## Vendor the grammar sources [Section titled “Vendor the grammar sources”](#vendor-the-grammar-sources) Before building with `TSLP_LANGUAGES`, you need the parser C sources locally: ```bash task clone ``` This runs `scripts/clone_vendors.py`, which checks out the correct revision for each grammar into `parsers/`. The script is idempotent — already-cloned grammars do not re-clone. To clone a specific language: The script has no command-line flags; select a subset with the `TSLP_LANGUAGES` environment variable (names not in `sources/language_definitions.json` are ignored with a warning): ```bash TSLP_LANGUAGES=python,rust python scripts/clone_vendors.py ``` ## Building the CLI [Section titled “Building the CLI”](#building-the-cli) ```bash cargo build -p ts-pack-cli # or cargo build --release -p ts-pack-cli ``` The release profile uses thin LTO, a single codegen unit, `opt-level = 3`, and strips debug symbols. ## Running tests [Section titled “Running tests”](#running-tests) ```bash # All Rust tests cargo test -p tree-sitter-language-pack # Run a single test cargo test -p tree-sitter-language-pack detect_language_from_extension # Criterion benchmarks cargo bench -p tree-sitter-language-pack ``` Run `task --list` to see all available task commands including per-binding test commands. # Chunking for LLMs > Split code at natural syntax boundaries for LLM ingestion — never mid-function, never mid-class. Naive line-count or character-count splitting breaks code apart at random. A function split across two chunks loses its signature. A class split mid-method gives the model half a definition. Syntax-aware chunking walks the concrete syntax tree and splits at natural boundaries. Here’s the difference: ```python def process_order(order_id: str, quantity: int) -> dict: """Process an order and return the result.""" # validate input if quantity <= 0: raise ValueError("quantity must be positive") item = fetch_item(order_id) price = item["price"] * quantity return {"order_id": order_id, "total": price, "status": "pending"} ``` Naive chunking at 100 bytes might split after `raise ValueError(...)`, leaving the return statement in the next chunk. Syntax-aware chunking keeps `process_order` together as one unit. The chunker splits inside a function when that function alone exceeds the byte budget. ## Basic usage [Section titled “Basic usage”](#basic-usage) Set `chunk_max_size` in `ProcessConfig` to enable chunking: * Python ```python from tree_sitter_language_pack import process, ProcessConfig with open("src/service.py") as f: source = f.read() result = process(source, ProcessConfig( language="python", chunk_max_size=1000, # max bytes per chunk structure=True, # include structure metadata )) for i, chunk in enumerate(result.chunks): print(f"Chunk {i + 1}: lines {chunk.start_line}-{chunk.end_line} " f"({chunk.end_byte - chunk.start_byte} bytes)") ``` * Node.js ```typescript import { process } from "@xberg-io/tree-sitter-language-pack"; import { readFileSync } from "fs"; const source = readFileSync("src/service.ts", "utf8"); const result = process(source, { language: "typescript", chunkMaxSize: 1000, structure: true, }); result.chunks.forEach((chunk, i) => { console.log(`Chunk ${i + 1}: lines ${chunk.startLine}-${chunk.endLine} (${chunk.endByte - chunk.startByte} bytes)`); }); ``` * Rust ```rust use tree_sitter_language_pack::{process, ProcessConfig}; let mut config = ProcessConfig::new("rust").with_chunking(1000); config.structure = true; let result = process(&source, &config)?; for (i, chunk) in result.chunks.iter().enumerate() { println!("Chunk {}: lines {}-{} ({} bytes)", i + 1, chunk.start_line, chunk.end_line, chunk.end_byte - chunk.start_byte); } ``` * CLI ```bash ts-pack process src/service.py --chunk-size 1000 \ | jq '.chunks[] | {lines: "\(.start_line)-\(.end_line)", bytes: (.end_byte - .start_byte)}' ``` ## Chunk fields [Section titled “Chunk fields”](#chunk-fields) | Field | Type | Description | | ------------ | -------------- | ------------------------------------- | | `content` | str | Source code text for this chunk | | `start_byte` | int | Inclusive start byte offset in source | | `end_byte` | int | Exclusive end byte offset in source | | `start_line` | int | First line (**zero-indexed**) | | `end_line` | int | Last line (**zero-indexed**) | | `metadata` | `ChunkContext` | Chunk metadata — see below | `metadata` (`ChunkContext`) carries `language`, `chunk_index`, `total_chunks`, `node_types`, `context_path`, `symbols_defined`, `comments`, `docstrings`, and `has_error_nodes`. Note that `node_types` lives on `chunk.metadata.node_types`, not on the chunk itself. ## How it works [Section titled “How it works”](#how-it-works) The chunker runs three passes: 1. Collect top-level declarations (functions, classes, methods) as atomic units. Comments and docstrings above a declaration attach to it. 2. Pack units into chunks without exceeding `chunk_max_size`. When the current chunk would overflow, close it and start a new one. 3. For any single unit that exceeds `chunk_max_size` on its own, split at the next logical sub-boundary — between methods in a class, or between statement blocks in a function. The result: functions are never split unless they’re individually too large, decorators stay with their function, and imports group into a single chunk at the top. ## Byte budget [Section titled “Byte budget”](#byte-budget) `chunk_max_size` is an upper bound in bytes, not a fixed size. The chunker may produce smaller chunks when a natural boundary falls before the limit. ## Structure metadata with chunks [Section titled “Structure metadata with chunks”](#structure-metadata-with-chunks) When `structure=True` is also set, each chunk’s `metadata.node_types` field shows what kind of code it contains. This is useful for metadata-enriched vector store ingestion: ```python config = ProcessConfig( language="python", chunk_max_size=1000, structure=True, docstrings=True, ) result = process(source, config) documents = [] for chunk in result.chunks: documents.append({ "content": chunk.content, "metadata": { "language": "python", "start_line": chunk.start_line, "end_line": chunk.end_line, "node_types": chunk.metadata.node_types, "size_bytes": chunk.end_byte - chunk.start_byte, } }) ``` ## Indexing a repository [Section titled “Indexing a repository”](#indexing-a-repository) A complete example that walks a codebase and produces LLM-ready chunks: ```python import os from pathlib import Path from tree_sitter_language_pack import process, ProcessConfig, has_language LANGUAGE_MAP = { ".py": "python", ".js": "javascript", ".ts": "typescript", ".rs": "rust", ".go": "go", ".java": "java", ".rb": "ruby", ".ex": "elixir", ".php": "php", ".cs": "csharp", ".cpp": "cpp", ".c": "c", } def chunk_repository(repo_path: str, chunk_size: int = 800) -> list[dict]: chunks = [] for root, _, files in os.walk(repo_path): for filename in files: ext = Path(filename).suffix language = LANGUAGE_MAP.get(ext) if not language or not has_language(language): continue filepath = os.path.join(root, filename) try: source = Path(filepath).read_text(encoding="utf-8", errors="ignore") except OSError: continue result = process(source, ProcessConfig( language=language, chunk_max_size=chunk_size, structure=True, imports=True, docstrings=True, )) for chunk in result.chunks: chunks.append({ "content": chunk.content, "file": filepath, "start_line": chunk.start_line, "end_line": chunk.end_line, "language": language, "node_types": chunk.metadata.node_types, "size_bytes": chunk.end_byte - chunk.start_byte, }) return chunks docs = chunk_repository("./my-project") print(f"{len(docs)} chunks from {len(set(d['file'] for d in docs))} files") ``` ## Next steps [Section titled “Next steps”](#next-steps) * [Code intelligence](/guides/intelligence/) — the other `ProcessConfig` fields that work alongside chunking * [Concepts: Code intelligence](/concepts/code-intelligence/) — the extraction engine design # CLI reference > CLI reference for ts-pack — download parsers, parse source code, and run code intelligence. `ts-pack` downloads tree-sitter parsers and runs code intelligence from the command line. ## Installation [Section titled “Installation”](#installation) * Cargo ```bash cargo install ts-pack-cli ``` Or grab the prebuilt binary with [cargo-binstall](https://github.com/cargo-bins/cargo-binstall): ```bash cargo binstall ts-pack-cli ``` * Homebrew (macOS / Linux) ```bash brew trust xberg-io/tap brew install xberg-io/tap/ts-pack ``` * Scoop (Windows) ```powershell scoop bucket add xberg https://github.com/xberg-io/scoop-bucket scoop install ts-pack ``` Verify the install: ```bash ts-pack --version ``` ## Commands [Section titled “Commands”](#commands) | Command | What it does | | ------------------------------------- | ----------------------------------------- | | [`download`](#ts-pack-download) | Download parser libraries | | [`clean`](#ts-pack-clean) | Remove cached parsers | | [`list`](#ts-pack-list) | List available languages | | [`info`](#ts-pack-info) | Show details about a language | | [`parse`](#ts-pack-parse) | Parse a file and output the syntax tree | | [`process`](#ts-pack-process) | Run code intelligence on a file | | [`cache-dir`](#ts-pack-cache-dir) | Print the cache directory path | | [`init`](#ts-pack-init) | Create a `language-pack.toml` config file | | [`mcp`](/guides/mcp-server/) | Run the MCP server for AI agents | | [`completions`](#ts-pack-completions) | Generate shell completions | *** ### `ts-pack download` [Section titled “ts-pack download”](#ts-pack-download) Download parser libraries to the local cache. ```bash ts-pack download [LANGUAGES...] [OPTIONS] ``` | Flag | Description | | ------------------- | --------------------------------------------------------------------------------------------------------------------------------- | | `--all` | Download all 371 parsers | | `--groups ` | Download by group (comma-separated). Only manifest-defined names are accepted; the published manifest defines exactly one, `all`. | | `--fresh` | Clear the cache before downloading | ```bash # Download specific parsers ts-pack download python javascript typescript # Download everything ts-pack download --all # Re-download from scratch, ignoring the cache ts-pack download python --fresh # Download a group ts-pack download --groups all # Download whatever languages-pack.toml specifies (if one is found) ts-pack download ``` Without arguments and with no `language-pack.toml` present, the command exits with an error. *** ### `ts-pack clean` [Section titled “ts-pack clean”](#ts-pack-clean) Remove all cached parser libraries. Prompts for confirmation unless you pass `--force`. ```bash ts-pack clean [OPTIONS] ``` | Flag | Description | | --------- | ---------------------------- | | `--force` | Skip the confirmation prompt | ```bash ts-pack clean # prompts: "Continue? [y/N]" ts-pack clean --force # no prompt ``` *** ### `ts-pack list` [Section titled “ts-pack list”](#ts-pack-list) List available languages. ```bash ts-pack list [OPTIONS] ``` | Flag | Description | | ----------------- | ------------------------------------------- | | `--downloaded` | Show only locally cached parsers | | `--manifest` | Show all languages from the remote manifest | | `--filter ` | Filter by substring | ```bash ts-pack list # all available languages ts-pack list --downloaded # only what's in the cache ts-pack list --filter script # languages whose name contains "script" ``` *** ### `ts-pack info` [Section titled “ts-pack info”](#ts-pack-info) Show details about a specific language. Usage ```text ts-pack info ``` ```bash ts-pack info python ``` Output when the parser has downloaded: ```text Language: python Known: true Downloaded: true Cache path: /home/user/.cache/tree-sitter-language-pack/v1.14.3/libs/libtree_sitter_python.so ``` Before the parser downloads, `Cache path` shows the cache directory instead. *** ### `ts-pack parse` [Section titled “ts-pack parse”](#ts-pack-parse) Parse source code and output the syntax tree. ```bash ts-pack parse [OPTIONS] ``` Use `-` as `FILE` to read from stdin (requires `--language`). | Flag | Description | | ------------------------- | ---------------------------------------------------------------- | | `--language `, `-l` | Language name. Auto-detected from the file extension if omitted. | | `--format `, `-f` | `sexp` (default) or `json` | ```bash ts-pack parse src/main.py ts-pack parse src/main.py --format json echo "def hello(): pass" | ts-pack parse - --language python ``` Sample `sexp` output: ```text (module (function_definition name: (identifier) parameters: (parameters) body: (block (expression_statement (call ...))))) ``` The JSON format wraps the sexp string alongside the language name and an `has_errors` boolean. *** ### `ts-pack process` [Section titled “ts-pack process”](#ts-pack-process) Run code intelligence on a source file and output structured JSON. ```bash ts-pack process [OPTIONS] ``` Use `-` as `FILE` to read from stdin. When reading from stdin, you must pass `--language`. | Flag | Description | | ------------------------- | ------------------------------------------------------- | | `--language `, `-l` | Language name. Auto-detected from extension if omitted. | | `--all` | Enable all analysis features | | `--structure` | Extract functions, classes, and methods | | `--imports` | Extract import statements | | `--exports` | Extract exported symbols | | `--comments` | Extract comments | | `--symbols` | Extract all identifiers | | `--docstrings` | Extract docstrings | | `--diagnostics` | Report syntax errors | | `--chunk-size ` | Split output into chunks of at most `n` bytes | Without any feature flags, the default extracts structure, imports, and exports. ```bash # Full analysis ts-pack process src/app.py --all # Structure only ts-pack process src/app.py --structure # Chunk a large file for LLM ingestion ts-pack process large_module.py --chunk-size 800 # From stdin cat src/main.go | ts-pack process - --language go --imports ``` *** ### `ts-pack cache-dir` [Section titled “ts-pack cache-dir”](#ts-pack-cache-dir) Print the effective cache directory path. /home/user/.cache/tree-sitter-language-pack/v1.14.3/libs ```bash ts-pack cache-dir # Use in scripts CACHE=$(ts-pack cache-dir) du -sh "$CACHE" ``` *** ### `ts-pack init` [Section titled “ts-pack init”](#ts-pack-init) Create a `language-pack.toml` config file in the current directory. ```bash ts-pack init [OPTIONS] ``` | Flag | Description | | --------------------- | -------------------------------------------------- | | `--cache-dir ` | Set a custom cache directory in the generated file | | `--languages ` | Comma-separated languages to pre-fill | ```bash ts-pack init ts-pack init --languages python,javascript,typescript,rust ``` Generated file (empty init): language-pack.toml ```toml # languages = ["python", "rust"] ``` With `--languages python,rust`: ```toml languages = ["python", "rust"] ``` After init, run `ts-pack download` to fetch the listed parsers. *** ### `ts-pack completions` [Section titled “ts-pack completions”](#ts-pack-completions) Generate shell completion scripts. Usage ```text ts-pack completions ``` Supported: `bash`, `zsh`, `fish`, `powershell`, `elvish`. ```bash ts-pack completions bash >> ~/.bash_completion ts-pack completions zsh > ~/.zsh/completions/_ts-pack ts-pack completions fish > ~/.config/fish/completions/ts-pack.fish ``` *** ## Exit codes [Section titled “Exit codes”](#exit-codes) | Code | Meaning | | ---- | --------------------------------- | | `0` | Success | | `1` | Error — message printed to stderr | *** ## Use in CI [Section titled “Use in CI”](#use-in-ci) Pre-download parsers and cache them between runs: ```yaml - name: Install ts-pack run: cargo install ts-pack-cli - name: Cache parsers uses: actions/cache@v4 with: path: ~/.cache/tree-sitter-language-pack key: tslp-${{ hashFiles('language-pack.toml') }} - name: Download parsers run: ts-pack download - name: Analyze run: ts-pack process src/main.py --all ``` # Configuration > Configuring tree-sitter-language-pack — cache directories, pre-downloads, and configuration discovery. Downloaded parser binaries go in the cache directory. The default: ```text ~/.cache/tree-sitter-language-pack//libs/ ``` You can customize the cache location, pre-download languages on startup, and wire up automatic discovery through a TOML file, the programmatic API, or CLI commands. ## Runtime environment variables [Section titled “Runtime environment variables”](#runtime-environment-variables) These are read at runtime by the downloader. | Variable | Description | | ---------------------------------------- | -------------------------------------------------------------------------------------------------------- | | `TREE_SITTER_LANGUAGE_PACK_CACHE_DIR` | Base directory for the parser cache; overrides the platform cache directory | | `TREE_SITTER_LANGUAGE_PACK_MANIFEST_URL` | Override the `parsers.json` manifest URL (`http(s)://` or `file://`) for mirrors and air-gapped installs | | `TREE_SITTER_LANGUAGE_PACK_TLS_ROOTS` | `platform` (default) or `webpki` — see [TLS trust store](#tls-trust-store) | The cache base is resolved in layers: `TREE_SITTER_LANGUAGE_PACK_CACHE_DIR` (when set and non-empty), else the platform cache directory, else the system temporary directory. The last resort keeps downloads working on hosts where the platform reports no cache directory (some Windows CI and conda-forge runners); it logs a `WARN` because a temp-dir cache is not guaranteed to persist between runs. ## Language-pack.toml [Section titled “Language-pack.toml”](#language-packtoml) Create `language-pack.toml` in your project root: language-pack.toml ```toml languages = ["python", "javascript", "typescript", "rust"] # Optional: language groups. Only names the remote manifest defines are accepted, # and it currently defines exactly one: "all". Enumerate with manifest_groups(). # groups = ["all"] # Optional: custom cache directory # cache_dir = ".cache/ts-pack" ``` Run `ts-pack init` to generate this file interactively, or create it by hand. ### Configuration discovery [Section titled “Configuration discovery”](#configuration-discovery) The library searches for `language-pack.toml` in this order: 1. Current directory and parent directories (up to 10 levels) 2. `$XDG_CONFIG_HOME/tree-sitter-language-pack/config.toml` (`~/.config/tree-sitter-language-pack/config.toml` on Linux/macOS) CLI flags override config file settings. ### Monorepo example [Section titled “Monorepo example”](#monorepo-example) ```toml # language-pack.toml (at repo root) languages = [ # Backend "python", # Frontend "javascript", "typescript", "jsx", "tsx", # Utilities "rust", "bash", "dockerfile", "yaml", "json", ] # Shared cache across all sub-projects cache_dir = ".cache/tree-sitter" ``` ## Programmatic API [Section titled “Programmatic API”](#programmatic-api) * Python `init()` and `configure()` take a single optional `PackConfig`; there are no keyword arguments. ```python from tree_sitter_language_pack import PackConfig, configure, init # Pre-download specific languages init(PackConfig(languages=["python", "javascript", "rust"])) # Download by language group. manifest_groups() lists the names that exist; # the published manifest defines only "all". init(PackConfig(groups=["all"])) # Combine languages and groups init(PackConfig(languages=["python"], groups=["all"])) # Set custom cache directory (call before first parse) configure(PackConfig(cache_dir="/opt/ts-pack-cache")) # With no argument, init() applies an empty PackConfig init() ``` TOML loading is Rust-only `PackConfig::from_toml_file()`, `PackConfig::discover()`, and `PackConfig::try_discover()` exist only on the Rust `PackConfig` (behind the `config` feature). They are not exported to Python or any other binding — the CLI (`ts-pack download`) reads `language-pack.toml` on your behalf. * Node.js ```typescript import { init, configure, PackConfig } from "@xberg-io/tree-sitter-language-pack"; init({ languages: ["python", "javascript", "rust"] }); init({ groups: ["all"] }); // "all" is the only group the manifest defines configure({ cacheDir: "/opt/ts-pack-cache" }); ``` * Rust ```rust use tree_sitter_language_pack::PackConfig; use std::path::Path; // Programmatic configuration let config = PackConfig { cache_dir: Some(Path::new("/opt/cache").to_path_buf()), languages: Some(vec!["python".to_string(), "rust".to_string()]), groups: None, }; // Load from file let config = PackConfig::from_toml_file(Path::new("language-pack.toml"))?; // Discover in parent directories. `None` means no config file was found, or one // was found but could not be read or parsed (a warning names the path in that case). if let Some(config) = PackConfig::discover() { println!("Found languages: {:?}", config.languages); } // `try_discover()` distinguishes "no config" from "broken config" instead of // collapsing both into `None`: `Ok(None)` means no config file was found, // `Err` means one was found but could not be read or parsed, and names the path. match PackConfig::try_discover() { Ok(Some(config)) => println!("Found languages: {:?}", config.languages), Ok(None) => println!("No config file found"), Err(e) => eprintln!("language-pack.toml found but invalid: {e}"), } ``` ## Build-time environment variables [Section titled “Build-time environment variables”](#build-time-environment-variables) `build.rs` reads these at compile time, not at runtime. See [Building from source](/guides/building/) for full details. | Variable | Description | | --------------------------------- | --------------------------------------------------------------------------------------------------- | | `TSLP_LANGUAGES` | Comma-separated languages to compile statically into the binary | | `TSLP_LINK_MODE` | `dynamic` (default), `static`, or `both` | | `PROJECT_ROOT` | Override directory search for `sources/language_definitions.json` | | `WASI_SYSROOT` | WASI sysroot path for `wasm32-wasi` cross-compilation | | `TSLP_OFFLINE` | Set to a non-empty, non-`0` value to refuse downloading the parser-source bundle | | `TSLP_SOURCE_BUNDLE_URL` | Override the URL of the `parser-sources-{version}.tar.zst` release asset | | `TSLP_ALLOW_FAILED_GRAMMARS` | Set to `1` to downgrade grammar compile failures to warnings (local debugging only) | | `TSLP_WASM_MAX_PARSER_BYTES` | `wasm32` only: `parser.c` size gate in bytes; `0` disables the gate | | `TSLP_WASM_SKIP_GRAMMARS` | `wasm32` only: comma-separated grammars to skip; replaces the default skip list (empty disables it) | | `TREE_SITTER_LANGUAGE_PACK_BUILD` | Set to `1` or `true` to force a rebuild of the Elixir NIF native extension | ## CLI commands [Section titled “CLI commands”](#cli-commands) ### `ts-pack init` [Section titled “ts-pack init”](#ts-pack-init) Create a `language-pack.toml`: ```bash # Interactive ts-pack init # With specific languages ts-pack init --languages python,javascript,typescript,rust # With custom cache directory ts-pack init --cache-dir ./local-cache --languages python ``` ### `ts-pack cache-dir` [Section titled “ts-pack cache-dir”](#ts-pack-cache-dir) Print the effective cache directory: ```bash ts-pack cache-dir # /home/user/.cache/tree-sitter-language-pack//libs/ # Use in scripts CACHE=$(ts-pack cache-dir) du -sh "$CACHE" ``` ### `ts-pack download` [Section titled “ts-pack download”](#ts-pack-download) ```bash # Languages from config ts-pack download # Specific languages ts-pack download python rust javascript # All available languages ts-pack download --all # Clear cache and re-download ts-pack download --fresh # By group ts-pack download --groups all ``` ### `ts-pack list` [Section titled “ts-pack list”](#ts-pack-list) ```bash # All available languages ts-pack list # Cached only ts-pack list --downloaded # Filter by name ts-pack list --filter python ``` ## TLS trust store [Section titled “TLS trust store”](#tls-trust-store) The downloader trusts the **host OS trust store** by default — the same set of CAs that `curl`, `pip`, and `git` use on each platform (`/etc/ssl/certs` on Linux, Keychain on macOS, SChannel on Windows). This works out of the box in corp environments where GitHub HTTPS traffic is presented with a chain rooted in a locally trusted CA (TLS-intercepting proxies, internal mirrors, WSL2 with Windows-managed certs, RHEL/UBI with extra anchors). Set `TREE_SITTER_LANGUAGE_PACK_TLS_ROOTS=webpki` to force the downloader to trust **only** the bundled Mozilla webpki roots (the historical pre-fix default). Use this on hosts whose platform trust store is intentionally narrowed or where you need byte-for-byte build reproducibility against a known root set: ```bash TREE_SITTER_LANGUAGE_PACK_TLS_ROOTS=webpki python -c "import tree_sitter_language_pack; tree_sitter_language_pack.get_parser('python')" ``` Set `TREE_SITTER_LANGUAGE_PACK_TLS_ROOTS=platform` to make the default explicit. Any other value falls back to the default (no hard error). ## Troubleshooting [Section titled “Troubleshooting”](#troubleshooting) **Downloads failing** ```bash ts-pack cache-dir # verify the cache path ts-pack download python # retry the download ts-pack clean # clear a corrupted cache ``` `UnknownIssuer` / `invalid peer certificate` errors mean the chain GitHub serves is not in the trust store the downloader is configured to use. The default (Platform mode) already reads the host trust store; if you set `TREE_SITTER_LANGUAGE_PACK_TLS_ROOTS=webpki` explicitly, switch back to `platform` (or unset the variable). If `curl https://github.com` also fails on the same host with the same error, fix the host trust store first — the language pack honours it. For offline environments: pre-download on a machine with network access, then copy the cache directory to the target machine. See [Docker](/guides/docker/) for baking parsers into a container image. **Disk space** ```bash du -sh ~/.cache/tree-sitter-language-pack # Move the cache to a larger drive mv ~/.cache/tree-sitter-language-pack /mnt/large-drive/ts-pack-cache ln -s /mnt/large-drive/ts-pack-cache ~/.cache/tree-sitter-language-pack ``` ## Next steps [Section titled “Next steps”](#next-steps) * [Building from source](/guides/building/) — compile-time flags and environment variables * [Docker](/guides/docker/) — bake parsers into container images * [Parsing code](/guides/parsing/) — syntax trees after languages finish downloading # Docker > Run ts-pack in Docker — a statically-linked Alpine image with all parsers compiled in. The Docker image ships a statically-linked `ts-pack` binary on Alpine Linux. The build process compiles all parsers at image build time; the container needs no internet access or runtime downloads. ## Quick start [Section titled “Quick start”](#quick-start) ```bash docker pull ghcr.io/xberg-io/tree-sitter-language-pack:latest # Parse a file by mounting the current directory docker run --rm \ -v "$(pwd):/work" -w /work \ ghcr.io/xberg-io/tree-sitter-language-pack:latest \ parse src/main.py # From stdin echo "def hello(): pass" | docker run --rm -i \ ghcr.io/xberg-io/tree-sitter-language-pack:latest \ parse - --language python ``` ## Image contents [Section titled “Image contents”](#image-contents) The image is two layers: 1. A Rust/Alpine builder that compiles `ts-pack-cli` with all parsers statically linked via `TSLP_LINK_MODE=static` 2. A minimal `alpine:latest` runtime containing `/usr/local/bin/ts-pack` The binary links statically against musl libc, so it runs on any Linux machine without extra dependencies. ## Building locally [Section titled “Building locally”](#building-locally) Before building, you need the parser C sources cloned locally: ```bash uv run scripts/clone_vendors.py ``` Then build the image from the repository root (the full context must be present): ```bash docker build -f docker/Dockerfile -t ts-pack . ``` The build takes several minutes — it compiles every grammar in `sources/language_definitions.json` from C. ## Verify the image [Section titled “Verify the image”](#verify-the-image) ```bash docker run --rm ts-pack --version docker run --rm ts-pack list | wc -l # → 379 (377 language names, plus a blank line and the "377 language(s)" total) ``` ## Use in CI [Section titled “Use in CI”](#use-in-ci) ```yaml # GitHub Actions jobs: analyze: runs-on: ubuntu-latest container: image: ghcr.io/xberg-io/tree-sitter-language-pack:latest steps: - uses: actions/checkout@v4 - name: Extract structure run: ts-pack process src/main.py --structure ``` ## Build a smaller image with a parser subset [Section titled “Build a smaller image with a parser subset”](#build-a-smaller-image-with-a-parser-subset) To target a language subset, set `TSLP_LANGUAGES` at build time: ```dockerfile FROM rust:alpine AS builder RUN apk add --no-cache musl-dev gcc g++ python3 bash WORKDIR /build COPY . . RUN TSLP_LANGUAGES=python,javascript,typescript \ TSLP_LINK_MODE=static \ PROJECT_ROOT=/build \ cargo build --release -p ts-pack-cli && \ strip target/release/ts-pack FROM alpine:latest COPY --from=builder /build/target/release/ts-pack /usr/local/bin/ts-pack ENTRYPOINT ["ts-pack"] ``` Run `TSLP_LANGUAGES=python,javascript,typescript uv run scripts/clone_vendors.py` first to fetch just those grammar sources — the script takes no command-line flags, only the `TSLP_LANGUAGES` environment variable. ## Multi-arch [Section titled “Multi-arch”](#multi-arch) The published image targets `linux/amd64` and `linux/arm64`. The `ci-docker.yaml` and `publish-docker.yaml` workflows handle this via `docker buildx`. # Extraction queries > Custom extraction queries are not part of the public API — use process(), bundled query sources, or manual AST traversal. ## Extraction queries [Section titled “Extraction queries”](#extraction-queries) Custom query execution helpers are not exported by the Rust crate or the generated language bindings. Use [`process()`](/guides/intelligence/) for supported code intelligence fields such as structure, imports, exports, comments, docstrings, symbols, diagnostics, metrics, and chunks. The implementation extracts these fields with manual AST traversal in the Rust core. Bundled query helper functions return query source strings only; they do not execute queries: | Helper | What it returns | | -------------------------------- | ------------------------------------- | | `get_highlights_query(language)` | `highlights.scm` source, when bundled | | `get_injections_query(language)` | `injections.scm` source, when bundled | | `get_locals_query(language)` | `locals.scm` source, when bundled | | `get_tags_query(language)` | `tags.scm` source, when bundled | | `get_indents_query(language)` | `indents.scm` source, when bundled | | `get_folds_query(language)` | `folds.scm` source, when bundled | If you need custom extraction, call [`get_parser()`](/guides/parsing/), parse the source with `Parser.parse(&str)` or `Parser.parse_bytes(&[u8])`, then walk the tree manually or run tree-sitter query APIs in your host language. ### Next steps [Section titled “Next steps”](#next-steps) * [Code intelligence](/guides/intelligence/) — built-in extraction for common patterns * [Parsing code](/guides/parsing/) — raw syntax trees and low-level node traversal # Code intelligence > Extract functions, imports, docstrings, and other structured information from source code. `process()` parses a file and walks the AST to return structured data: the functions and classes defined in it, what it imports, its docstrings, comments, and more. You configure what to extract; the Rust core handles the manual extraction. It does not expose a built-in arbitrary query execution API. Here’s what a typical result looks like: * Python ```python from tree_sitter_language_pack import process, ProcessConfig source = ''' import os from pathlib import Path def read_file(path: str) -> str: """Read and return file contents.""" return Path(path).read_text() class FileCache: """Cache for file contents.""" def __init__(self, root: str): self.root = root def get(self, name: str) -> str: """Return cached file contents.""" return read_file(os.path.join(self.root, name)) ''' result = process(source, ProcessConfig( language="python", structure=True, imports=True, docstrings=True, )) for item in result.structure: doc = f" - {item.doc_comment}" if item.doc_comment else "" span = item.span print(f"{item.kind:8} {item.name:20} lines {span.start_line}-{span.end_line}{doc}") print() for imp in result.imports: names = ", ".join(imp.items) or "*" print(f"from {imp.source} import {names}") ``` Output (line numbers are zero-indexed): ```text Function read_file lines 4-6 - Read and return file contents. Class FileCache lines 8-17 - Cache for file contents. from os import * from pathlib import Path ``` Methods are not flattened into the top level — they appear in the owning item’s `children` list. * Node.js ```typescript import { process } from "@xberg-io/tree-sitter-language-pack"; const result = process(source, { language: "typescript", structure: true, imports: true, docstrings: true, }); result.structure.forEach((item) => { const doc = item.docComment ? ` — ${item.docComment}` : ""; console.log(`${(item.name ?? "").padEnd(20)} lines ${item.span?.startLine}-${item.span?.endLine}${doc}`); }); ``` * Rust ```rust use tree_sitter_language_pack::{process, ProcessConfig}; let mut config = ProcessConfig::new("rust"); config.structure = true; config.imports = true; config.docstrings = true; let result = process(source, &config)?; for item in &result.structure { println!("{:?} {:?} lines {}-{}", item.kind, item.name, item.span.start_line, item.span.end_line); } ``` * CLI ```bash # Extract structure and docstrings ts-pack process src/app.py --structure --docstrings # All fields, JSON output ts-pack process src/app.py --all | jq '.structure' ``` ## ProcessConfig fields [Section titled “ProcessConfig fields”](#processconfig-fields) Pass `language` plus any of these fields: | Field | Default | What it extracts | | ----------------- | ------- | ----------------------------------------------------------------------- | | `structure` | `True` | Functions, classes, methods, interfaces, structs, traits, enums | | `imports` | `True` | Import/require statements — source module and imported names | | `exports` | `True` | Exported symbols | | `comments` | `False` | All comments with text and location | | `docstrings` | `False` | Docstrings attached to declarations (requires `structure=True`) | | `symbols` | `False` | Deduplicated list of all identifiers, for search indexing | | `diagnostics` | `False` | Syntax error nodes from the parse | | `data_extraction` | `False` | Hierarchical key-value tree for structured data formats | | `chunk_max_size` | `None` | Maximum chunk size in bytes; see [Chunking for LLMs](/guides/chunking/) | In Rust, enable everything at once with `ProcessConfig::new("python").all()` (and the inverse, `.minimal()`); Ruby exposes the same `all` / `minimal` / `with_chunking` helpers. The public Python `ProcessConfig` is a frozen dataclass with no helper methods — set the fields you want directly. ## Result fields [Section titled “Result fields”](#result-fields) ### `structure` [Section titled “structure”](#structure) Each item has: | Field | Type | Description | | ------------- | --------------- | ---------------------------------------------------------- | | `kind` | `StructureKind` | See the kind list below | | `name` | str \| None | Declaration name, when the grammar exposes one | | `visibility` | str \| None | Visibility modifier (`"pub"`, `"public"`, `"private"`) | | `span` | `Span` | Source location of the whole declaration | | `children` | list | Nested items — a class’s methods live here | | `decorators` | `list[str]` | Decorator or attribute names applied to the item | | `doc_comment` | str \| None | Attached doc comment — only present when `docstrings=True` | | `signature` | str \| None | Full signature text | | `body_span` | `Span` \| None | Span of the body alone, when distinct from the declaration | `StructureKind` is a closed set, serialized as a **PascalCase bare string**: `"Function"`, `"Method"`, `"Class"`, `"Struct"`, `"Interface"`, `"Enum"`, `"Module"`, `"Trait"`, `"Impl"`, `"Namespace"`. Anything a grammar exposes that does not map to one of those is reported as `Other`, which serializes as a single-keyed object: `{"Other": "macro"}`. ### `Span` [Section titled “Span”](#span) Every location in a `ProcessResult` is a `Span`. All of its line and column numbers are **zero-indexed** — add 1 before displaying them next to editor line numbers. | Field | Type | Description | | -------------- | ---- | --------------------------- | | `start_byte` | int | Inclusive start byte offset | | `end_byte` | int | Exclusive end byte offset | | `start_line` | int | Zero-indexed start line | | `start_column` | int | Zero-indexed start column | | `end_line` | int | Zero-indexed end line | | `end_column` | int | Zero-indexed end column | ### `imports` [Section titled “imports”](#imports) Each import has `source` (module path), `items` (list of imported identifiers — empty for wildcard or bare imports), `alias` (`import numpy as np`), `is_wildcard`, and `span`. Covers both `import x` and `from x import y` in Python, both `import` and `require()` in JavaScript. ### `exports` [Section titled “exports”](#exports) Language-specific: * Python: module-level items not prefixed with `_`, or listed in `__all__` * JavaScript/TypeScript: explicit `export` declarations * Rust: items with `pub` visibility Each export has `name`, `kind` (`"Named"`, `"Default"`, or `"ReExport"`), and `span`. ### `comments` [Section titled “comments”](#comments) Each comment has `text`, `kind` (`"Line"`, `"Block"`, or `"Doc"`), `span`, and an optional `associated_node`. ### `docstrings` [Section titled “docstrings”](#docstrings) `result.docstrings` is a list of `DocstringInfo` — each with `text`, `format` (`"PythonTripleQuote"`, `"JSDoc"`, `"Rustdoc"`, `"GoDoc"`, `"JavaDoc"`, or `{"Other": "..."}`), `span`, `associated_item`, and `parsed_sections`. The same text also attaches to the owning `structure` item as its `doc_comment` field. Extraction understands each language’s convention: | Language | Convention | | --------------------- | ---------------------------------------------- | | Python | `"""..."""` immediately after `def`/`class` | | Rust | `///` or `//!` above the item | | JavaScript/TypeScript | `/** ... */` JSDoc above the function | | Java | `/** ... */` Javadoc | | Ruby | `# ...` lines immediately before `def`/`class` | | Go | `// FuncName ...` comment block above the func | | Elixir | `@doc "..."` or `@moduledoc "..."` | ### `symbols` [Section titled “symbols”](#symbols) A list of `SymbolInfo` **structs** — not bare strings. Each has `name`, `kind` (`"Variable"`, `"Constant"`, `"Function"`, `"Class"`, `"Type"`, `"Interface"`, `"Enum"`, `"Module"`, or `{"Other": "..."}`), `span`, `type_annotation`, and `doc`. Useful for search indexing: ```python result = process(source, ProcessConfig(language="python", symbols=True)) for symbol in result.symbols[:5]: print(symbol.kind, symbol.name, symbol.span.start_line) ``` ### `diagnostics` [Section titled “diagnostics”](#diagnostics) Syntax error nodes. A non-empty list does not mean the file has a parse error — tree-sitter recovers and produces a partial tree. Each `Diagnostic` has `message`, `severity` (`"Error"`, `"Warning"`, or `"Info"`), and `span`. ```python result = process(source, ProcessConfig(language="python", diagnostics=True)) for err in result.diagnostics: print(f"{err.severity} line {err.span.start_line}, col {err.span.start_column}: {err.message}") ``` ### `metrics` [Section titled “metrics”](#metrics) File-level statistics, independent of the other fields: | Field | Type | Description | | --------------- | ---- | ---------------------------------------- | | `total_lines` | int | All lines | | `code_lines` | int | Non-blank, non-comment lines | | `comment_lines` | int | Comment lines | | `blank_lines` | int | Empty lines | | `total_bytes` | int | Total byte length of the source | | `node_count` | int | Total number of nodes in the syntax tree | | `error_count` | int | Number of error nodes in the syntax tree | | `max_depth` | int | Maximum nesting depth of the syntax tree | ```python result = process(source, ProcessConfig(language="python")) m = result.metrics print(f"{m.total_lines} lines total, {m.code_lines} code, {m.comment_lines} comments") ``` ### `chunks` [Section titled “chunks”](#chunks) When `chunk_max_size` has a value, `result.chunks` contains syntax-aware splits ready for LLM ingestion. See [Chunking for LLMs](/guides/chunking/) for full documentation. ## Data extraction [Section titled “Data extraction”](#data-extraction) Set `data_extraction = true` on `ProcessConfig` to extract a hierarchical `DataNode` tree from structured-data languages. Instead of parsing code, this returns a nested key-value structure preserving the original document’s hierarchy. This is available through the `process()` API and generated bindings. The `ts-pack process` CLI does not expose a `data_extraction` flag. Supported identifiers (19): `json`, `hjson`, `json5`, `toml`, `properties`, `hcl`, `hocon`, `kdl`, `cue`, `yaml`, `ini`, `editorconfig`, `csv`, `psv`, `po`, `nginx`, `caddy`, `xml`, `dtd`. ### DataNode shape [Section titled “DataNode shape”](#datanode-shape) Each node contains: | Field | Type | Description | | ------------ | ------------------------------------- | --------------------------------------------------------------------------------------------------- | | `kind` | `KeyValue` \| `Element` \| `Sequence` | Node type: key-value pair, XML element, or sequence item | | `key` | string \| None | Key name, attribute name, tag name, or positional index (“0”, “1”, …). `None` at document root. | | `value` | string \| None | Leaf value if present. `None` for containers (objects, arrays, XML elements with children). | | `attributes` | array | Attributes on XML elements; empty for other node types. | | `children` | array | Nested child nodes for containers and XML element bodies. | | `span` | object | Source location (`start_byte`, `end_byte`, `start_line`, `start_column`, `end_line`, `end_column`). | ### Examples [Section titled “Examples”](#examples) **JSON nested object:** ```python result = process(''' { "server": { "host": "localhost", "port": 8080 } } ''', ProcessConfig(language="json", data_extraction=True)) # result.data.kind = "KeyValue" # result.data.key = None # result.data.children[0].key = "server" # result.data.children[0].children[0].key = "host" # result.data.children[0].children[0].value = "localhost" # result.data.children[0].children[1].key = "port" # result.data.children[0].children[1].value = "8080" ``` **Properties flat key-value (issue #136):** ```java // configuration.properties: // database.url=jdbc:postgres://localhost // database.port=5432 // cache.ttl=3600 // ProcessConfig is a record with a Jackson builder using the "with" prefix. ProcessResult result = TreeSitterLanguagePack.process(propertiesSource, ProcessConfig.builder() .withLanguage("properties") .withDataExtraction(true) .build()); // DataNode is a record — accessors are the component names, not getX(). for (DataNode pair : result.data().children()) { System.out.println(pair.key() + " = " + pair.value()); } ``` **YAML with nested mapping:** ```python result = process(''' database: primary: host: db.example.com user: admin replica: host: db-replica.example.com user: readonly ''', ProcessConfig(language="yaml", data_extraction=True)) # result.data.children[0].key = "database" # result.data.children[0].children[0].key = "primary" # result.data.children[0].children[0].children[0].key = "host" ``` **TOML sections:** ```python result = process(''' [build] name = "my-app" version = "1.0" ''', ProcessConfig(language="toml", data_extraction=True)) # result.data.children[0].key = "build" # result.data.children[0].children = [ # {"key": "name", "value": "my-app", ...}, # {"key": "version", "value": "1.0", ...} # ] ``` **XML elements with attributes:** ```python result = process(''' ''', ProcessConfig(language="xml", data_extraction=True)) # result.data.children[0].kind = "Element" # result.data.children[0].key = "server" # result.data.children[0].attributes = [ # {"name": "host", "value": "localhost"}, # {"name": "port", "value": "8080"} # ] # result.data.children[0].children = [ # {"kind": "Element", "key": "ssl", "attributes": [...], ...} # ] ``` ## Next steps [Section titled “Next steps”](#next-steps) * [Chunking for LLMs](/guides/chunking/) — split code at natural boundaries for LLM ingestion * [Parsing code](/guides/parsing/) — raw syntax trees and low-level node traversal # MCP Server > Set up the tree-sitter-language-pack MCP server for AI agents — stdio and HTTP transport, IDE integration with Claude Code, Cursor, VS Code. The tree-sitter-language-pack CLI includes an MCP server that exposes parsing, code intelligence extraction, language detection, and cache management as standard tools for AI agents. Use it to add code analysis to Claude, Cursor, VS Code, or any MCP-compatible application. There are three ways to run it: * **Bundled with the plugin** — the [coding-agent plugin](/guides/ai-coding-assistants/) registers the `tree-sitter-language-pack` MCP server for you and resolves the CLI automatically. Nothing to install by hand. * **Direct MCP client config** — point any MCP client at the published `ts-pack` CLI (see [Installing the CLI](#installing-the-cli) below). * **Hermes** — for Hermes-based agents, install the runtime plugin with `pip install tree-sitter-language-pack-hermes-plugin`. ## Installing the CLI [Section titled “Installing the CLI”](#installing-the-cli) The `ts-pack` binary is published to every major registry. Install it with whichever fits your toolchain: ```bash # Homebrew (macOS / Linux) brew install xberg-io/tap/ts-pack # Scoop (Windows) -- run these two in PowerShell # scoop bucket add xberg https://github.com/xberg-io/scoop-bucket # scoop install ts-pack # npm (Node.js) npm install -g @xberg-io/ts-pack-cli # uv / uvx (Python) uvx --from ts-pack-cli ts-pack --version # Cargo (Rust) cargo install ts-pack-cli ``` Once `ts-pack` is on your `PATH`, any of the client configs below will work. ## What is MCP? [Section titled “What is MCP?”](#what-is-mcp) The [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) is an open standard for connecting AI applications to tools and data. The tree-sitter-language-pack MCP server provides tools for parsing source code, analyzing structure and symbols, and managing language packs — all through a unified interface. ## Starting the Server [Section titled “Starting the Server”](#starting-the-server) ### Stdio Transport (Default) [Section titled “Stdio Transport (Default)”](#stdio-transport-default) For local AI tools — Claude Desktop, Cursor, VS Code — use stdio transport: ```bash ts-pack mcp --transport stdio ``` Stdio is the default, so `ts-pack mcp` is equivalent. The server runs as a subprocess and communicates over stdin/stdout with JSON-RPC messages. No network configuration needed. ### HTTP Transport [Section titled “HTTP Transport”](#http-transport) For remote agents or team environments where stdio doesn’t work: ```bash ts-pack mcp --transport http --host 127.0.0.1 --port 8011 ``` The server listens on `http://127.0.0.1:8011` (default). Change `--host` to `0.0.0.0` for network-wide access (use with caution). ### Custom Configuration [Section titled “Custom Configuration”](#custom-configuration) Point the server at a `language-pack.toml` config file: ```bash ts-pack mcp --config /path/to/language-pack.toml ``` This sets default languages and download preferences for all tool calls. ## Registering with AI Tools [Section titled “Registering with AI Tools”](#registering-with-ai-tools) ### Claude Desktop / Claude Code [Section titled “Claude Desktop / Claude Code”](#claude-desktop--claude-code) Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or `%APPDATA%\Claude\claude_desktop_config.json` (Windows): ```json { "mcpServers": { "tree-sitter-language-pack": { "command": "ts-pack", "args": ["mcp", "--transport", "stdio"] } } } ``` Or use the CLI to register automatically: ```bash claude mcp add tree-sitter-language-pack -- ts-pack mcp --transport stdio ``` Restart Claude. The tree-sitter-language-pack tools appear in the Tools panel. ### Cursor [Section titled “Cursor”](#cursor) Edit `.cursor/mcp.json` in your project root (or global Cursor settings): ```json { "mcpServers": { "tree-sitter-language-pack": { "command": "ts-pack", "args": ["mcp", "--transport", "stdio"] } } } ``` Reload Cursor. Tools are now available in the AI chat. ### VS Code / GitHub Copilot [Section titled “VS Code / GitHub Copilot”](#vs-code--github-copilot) Edit `.vscode/settings.json` or your VS Code global settings: ```json { "mcpServers": [ { "name": "tree-sitter-language-pack", "command": "ts-pack", "args": ["mcp", "--transport", "stdio"] } ] } ``` Then reference tools in GitHub Copilot chat or use the Tools panel. ### Generic MCP Client [Section titled “Generic MCP Client”](#generic-mcp-client) For a client that spawns the server over stdio, point it at the `ts-pack` binary: ```json { "mcpServers": [ { "name": "tree-sitter-language-pack", "command": "ts-pack", "args": ["mcp", "--transport", "stdio"] } ] } ``` For an HTTP client, start the server yourself (`ts-pack mcp --transport http --port 8011`) and connect to its URL: ```json { "mcpServers": [ { "name": "tree-sitter-language-pack", "url": "http://127.0.0.1:8011" } ] } ``` ## Tools [Section titled “Tools”](#tools) The MCP server exposes 8 tools for parsing, analysis, and management: * Parsing & Analysis **`parse`** Render the syntax tree as S-expression or JSON. | Parameter | Type | Description | | ---------- | ------ | ------------------------------------------------- | | `source` | string | Source code to parse | | `language` | string | Language name (e.g., `python`, `rust`) | | `format` | string | Output format: `sexp` or `json` (default: `sexp`) | **`process`** Extract code intelligence: structure, imports, exports, symbols, docstrings, comments, diagnostics, and optionally chunk for LLMs. | Parameter | Type | Description | | ----------------- | ------- | ----------------------------------------------------------------------- | | `source` | string | Source code to analyze | | `language` | string | Language name | | `all` | boolean | Enable every analysis feature; overrides the individual flags when true | | `structure` | boolean | Extract structural items (default: true) | | `imports` | boolean | Extract import statements (default: true) | | `exports` | boolean | Extract export statements (default: true) | | `comments` | boolean | Extract comments (default: false) | | `symbols` | boolean | Extract symbol definitions (default: false) | | `docstrings` | boolean | Extract docstrings (default: false) | | `diagnostics` | boolean | Include parse diagnostics (default: false) | | `data_extraction` | boolean | Hierarchical data extraction for data formats (default: false) | | `chunk_max_size` | integer | Maximum chunk size in bytes; omit to disable chunking | There is no `chunk_overlap` parameter — chunks never overlap. **`detect_language`** Identify language from a file path, source content, or both. Both parameters are optional; supply at least one. | Parameter | Type | Description | | --------- | ------ | ---------------------------------------------------------------- | | `path` | string | File path or name, used for extension-based detection — optional | | `content` | string | Source content, used for content-based detection — optional | * Languages & Discovery **`list_languages`** Enumerate available, downloaded, or manifest languages. | Parameter | Type | Description | | --------- | ------ | ---------------------------------------------------------------------- | | `source` | string | Which set to query: `available` (default), `downloaded`, or `manifest` | | `filter` | string | Substring filter applied to the result — optional | **`info`** Get status of a specific language (known to this build, downloaded, cache directory). | Parameter | Type | Description | | ---------- | ------ | ------------------------------ | | `language` | string | Language name (e.g., `python`) | **`download`** Fetch language parsers for offline use. | Parameter | Type | Description | | ----------- | ------- | -------------------------------------------------------------------------------------------------------------------------------- | | `languages` | array | List of language names — optional | | `all` | boolean | Download every available language — optional | | `groups` | array | Named groups to download. Only manifest-defined names are accepted; the published manifest defines exactly one, `all` — optional | | `fresh` | boolean | Clean the cache before downloading (default: false) | * Cache & Configuration **`cache_dir`** Retrieve the local cache directory where parsers are stored. Takes no parameters. Returns `{ "cache_dir": "/tree-sitter-language-pack/v{version}/libs" }`. **`clean_cache`** Delete **all** cached parsers. Takes no parameters — there is no per-language variant. Returns `{ "cache_dir": "…", "status": "cleared" }`. ## Resources [Section titled “Resources”](#resources) The MCP server provides read-only resources for browsing the language catalog: * **`ts-pack://languages`** — list of all 371 available languages with extensions and aliases * **`ts-pack://languages/downloaded`** — list of user-downloaded languages * **`ts-pack://language/{name}`** — status of a specific language (template resource) ## Prompt [Section titled “Prompt”](#prompt) The MCP server includes a built-in prompt template: **`analyze-code`** Returns a user message instructing the agent to call the `process` tool with `all=true`, then summarize the design, key entry points, and any issues. The prompt does not take the source code itself — the agent supplies it when it calls `process`. | Parameter | Type | Required | Description | | ---------- | ------ | -------- | ---------------------------------------------------------------------- | | `language` | string | Yes | Language name. Supports argument completion against the language list. | | `focus` | string | No | Free-form area to emphasize, e.g. `security` or `public API`. | `focus` is not a closed enum — whatever string you pass is appended to the prompt as “Pay particular attention to: …”. Omitting `language` falls back to the literal phrase “the file’s language”. ## Using the Plugin Instead [Section titled “Using the Plugin Instead”](#using-the-plugin-instead) For most users, installing the tree-sitter-language-pack plugin from the self-hosted [`xberg-io/tree-sitter-language-pack`](https://github.com/xberg-io/tree-sitter-language-pack) marketplace is simpler than manual MCP registration. The plugin ships a launcher script (`scripts/mcp-launch.sh`) that resolves the `ts-pack` CLI at runtime — via a cached binary, `npx @xberg-io/ts-pack-cli`, `uvx --from ts-pack-cli ts-pack`, Homebrew, or a prebuilt release download — and registers the `tree-sitter-language-pack` server for you. See [AI Coding Assistants](/guides/ai-coding-assistants/) for installation steps. ## Next Steps [Section titled “Next Steps”](#next-steps) * [CLI Guide](/guides/cli/) — full CLI command reference * [Parsing Code](/guides/parsing/) — understanding syntax trees * [Code Intelligence](/guides/intelligence/) — extract structure and symbols * [Installation](/getting-started/installation/) — install ts-pack-cli # Parsing code > Parse source code with the Rust API or CLI and inspect tree-sitter syntax trees. The stable public API for low-level syntax-tree parsing is `get_parser()`. It returns the package’s `Parser` wrapper configured for one of the bundled languages. Language bindings expose `process()` for structured analysis. Use `process()` unless you need a raw syntax tree or a manual AST walk. * Rust ```rust use tree_sitter_language_pack::get_parser; let mut parser = get_parser("python")?; let tree = parser .parse("def greet(name: str) -> str:\n return f\"Hello {name}\"\n") .ok_or("failed to parse source")?; let root = tree.root_node(); println!("{}", root.to_sexp()); # Ok::<(), Box>(()) ``` * CLI ```bash # Print the syntax tree for a file ts-pack parse main.py # Output as JSON ts-pack parse main.py --format json ``` For batch processing in Rust, reuse the parser object. Creating one parser per parse works at small scale but adds avoidable setup overhead when processing a large file set for the same language. Language names Names are case-sensitive — use the lowercase canonical form. Aliases exist: `shell` -> `bash`, `makefile` -> `make`, `bazel` -> `starlark`. See [Languages](/languages/) for the full list. ## The syntax tree [Section titled “The syntax tree”](#the-syntax-tree) Every parse returns a `Tree` with a single root node. Its kind is the top-level grammar node for the language: `module` for Python, `program` for JavaScript, `source_file` for Rust and Go. ```rust let mut parser = get_parser("python")?; let tree = parser .parse("def foo(): pass\ndef bar(): pass") .ok_or("failed to parse source")?; let root = tree.root_node(); println!("{}", root.kind()); // "module" println!("{:?}", root.start_position()); println!("{:?}", root.end_position()); println!("{}", root.child_count()); // 2 println!("{}", root.has_error()); // false # Ok::<(), Box>(()) ``` ## Field names [Section titled “Field names”](#field-names) Grammars assign named fields to semantically meaningful children. A Python `function_definition` has `name`, `parameters`, `return_type`, and `body`. Use `child_by_field_name` to reach them directly: ```rust let mut parser = get_parser("python")?; let tree = parser .parse("def add(a, b):\n return a + b") .ok_or("failed to parse source")?; let root = tree.root_node(); let func = root.child(0).ok_or("missing function")?; let name = func.child_by_field_name("name").ok_or("missing function name")?; let params = func .child_by_field_name("parameters") .ok_or("missing parameters")?; // `Node` is a zero-copy view: slice your own source bytes with `byte_range()`. let source = "def add(a, b):\n return a + b"; let name_range = name.byte_range(); let params_range = params.byte_range(); println!("{}", &source[name_range.start..name_range.end]); // "add" println!("{}", &source[params_range.start..params_range.end]); // "(a, b)" # Ok::<(), Box>(()) ``` Field names are grammar-specific. To discover them, run `ts-pack parse file.py` and read the labelled S-expression output. Field names appear as `name:`, `parameters:`, `body:` before each child. ## Named vs. anonymous nodes [Section titled “Named vs. anonymous nodes”](#named-vs-anonymous-nodes) Named nodes carry semantic meaning (`identifier`, `call_expression`, `string`). Anonymous nodes are punctuation and keywords (`(`, `)`, `def`, `:`). Iterate `named_child(i)` over `named_child_count()` when you want semantic nodes and no punctuation tokens. ```rust for i in 0..root.named_child_count() { let child = root.named_child(i as u32).ok_or("missing named child")?; println!("{}", child.kind()); } # Ok::<(), Box>(()) ``` ## Syntax errors [Section titled “Syntax errors”](#syntax-errors) Tree-sitter does not raise on malformed syntax. It marks problem areas with `ERROR` or `MISSING` nodes and keeps parsing. ```rust let mut parser = get_parser("python")?; let tree = parser .parse("def broken(") .ok_or("failed to parse source")?; println!("{}", tree.root_node().has_error()); // true ``` `has_error` on the root is a fast way to check whether any errors exist before walking. For structured diagnostics, use `process()` with diagnostics enabled. ## Node properties [Section titled “Node properties”](#node-properties) | Property | Description | | --------------------- | ---------------------------------------------------- | | `kind()` | Grammar node type, for example `function_definition` | | `start_position()` | `(row, column)`, zero-indexed | | `end_position()` | `(row, column)`, zero-indexed | | `start_byte()` | Byte offset in source | | `end_byte()` | Byte offset in source | | `child_count()` | All children including anonymous nodes | | `named_child_count()` | Named children only | | `byte_range()` | `ByteRange { start, end }` — slice your own source | | `named_child(i)` | The i-th named child, or `None` | | `has_error()` | True if any error nodes exist in this subtree | | `is_named()` | False for anonymous nodes like `(` or `def` | | `parent()` | Enclosing node, or `None` for the root | ## Language passthrough support [Section titled “Language passthrough support”](#language-passthrough-support) `get_language(name)` (or `getLanguage` in Node.js) returns a language handle in the most idiomatic shape for each binding. Where the ecosystem ships a native tree-sitter library, the returned value is the real `Language` object from that library, ready to feed into the local `Parser`. Where no such library exists or the library does not accept a raw pointer constructor, the binding returns an opaque handle. ### Passthrough bindings (host-native Language) [Section titled “Passthrough bindings (host-native Language)”](#passthrough-bindings-host-native-language) These return the ecosystem’s native `Language` type, ready to use with that ecosystem’s parser: | Binding | Returns | Use with | On unknown language | | -------------- | ------------------------------------------- | -------------------------------------- | ---------------------------------------------- | | Rust | `tree_sitter::Language` | `tree_sitter::Parser::set_language` | `Result` — propagate with `?` | | Python | `tree_sitter.Language` (PyCapsule) | `tree_sitter.Parser(language)` | Raises `LanguageNotFoundError` | | Node.js | `tree-sitter` npm `Language` | `new Parser().setLanguage(lang)` | Throws an `Error` | | Go | `*tree_sitter.Language` | `parser.SetLanguage(lang)` | Returns `(nil, error)` | | Java | `io.github.treesitter.jtreesitter.Language` | `new Parser().setLanguage(lang)` | Throws `TreeSitterLanguagePackRsException` | | C# | `TreeSitter.Language` | `new Parser().SetLanguage(lang)` | Throws `TreeSitterLanguagePackException` | | Kotlin Android | `io.github.treesitter.ktreesitter.Language` | `Parser(...).setLanguage(lang)` | Throws the binding’s bridge exception | | Swift | `SwiftTreeSitter.Language` | `Parser().setLanguage(lang)` | Throws `TreeSitterLanguagePackError` | | Zig | `?*const tree_sitter.Language` | `Parser.setLanguage(lang)` | Returns a Zig error (`Error!…`) | | C FFI | `const TSLanguage *` (borrowed) | `ts_parser_set_language(parser, lang)` | Returns `NULL` (do not `free` the result) | On a passthrough binding the handle is the ecosystem’s own `Language`, so it drops straight into existing tree-sitter code — add this package as a grammar source without touching the rest of your parsing setup. In Python, `get_language()` returns a real `tree_sitter.Language` (a `PyCapsule`-backed object) that the upstream `tree_sitter.Parser` accepts directly: ```python import tree_sitter from tree_sitter_language_pack import get_language language = get_language("python") # a tree_sitter.Language parser = tree_sitter.Parser(language) tree = parser.parse(b"def f(x):\n return x + 1\n") print(tree.root_node.type) # "module" ``` This restores the pre-1.9 ability to pass the handle to a separately installed `tree_sitter` (or `tree-sitter` on npm). If you do not already depend on the ecosystem library, prefer `get_parser(name)` — it returns a ready-to-use parser with no second dependency. ### Opaque-handle bindings [Section titled “Opaque-handle bindings”](#opaque-handle-bindings) These return an opaque handle specific to this package. Use the higher-level `process()` function or this package’s `getParser()`/`get_parser()` method rather than reaching for the ecosystem’s tree-sitter library. | Binding | Returns | Recommendation | | ------- | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | Ruby | opaque handle | Use this package’s `Parser` wrapper or `process()` | | PHP | opaque handle | Use this package’s extension API; `talbergs/php-tree-sitter` FFI not exposed | | Elixir | opaque handle | Use this package’s NIF wrapper; `ResourceArc` is NIF-private | | Dart | opaque handle | `flutter_rust_bridge` marshals Rust types as Arc-counted opaque proxies and never exposes the raw `const TSLanguage *` passthrough needs, and there is no maintained Dart tree-sitter package to construct from it — use the generated parser wrapper | | WASM | opaque handle | Use this package’s wrapper; `web-tree-sitter` runs in separate WASM memory | ## Next steps [Section titled “Next steps”](#next-steps) * [Code intelligence](/guides/intelligence/) — extract functions, imports, docstrings, and symbols without writing a tree walker * [Extraction queries](/guides/extraction/) — public API status for custom query helpers * [Languages](/languages/) — all 371 supported languages and their aliases # Performance and benchmarks > Run and interpret the Criterion benchmarks for tree-sitter-language-pack. The Rust core ships a [Criterion](https://bheisler.github.io/criterion.rs/book/) benchmark suite in `crates/ts-pack-core/benches/benchmarks.rs`. This guide explains how to run them and what each group measures. ## Running benchmarks [Section titled “Running benchmarks”](#running-benchmarks) ```bash cargo bench -p tree-sitter-language-pack ``` Criterion writes HTML reports to `target/criterion/`. Open `target/criterion/report/index.html` in a browser to see throughput charts across runs. To run a single group: ```bash # Just the parse benchmarks cargo bench -p tree-sitter-language-pack -- parse # Just language detection cargo bench -p tree-sitter-language-pack -- language_detection ``` ## Benchmark groups [Section titled “Benchmark groups”](#benchmark-groups) The suite covers four groups. Fixtures compile in from `fixtures/bench/`, with small (\~11 lines), medium (\~97 lines), and large (\~723 lines) variants for each of four languages: Python, TypeScript, Rust, and Go. ### `parse` [Section titled “parse”](#parse) Measures `get_parser(...).parse(...)` across all four languages at all three sizes. This is the baseline — a single tree-sitter parse with no post-processing. 12 cases: `python/small`, `python/medium`, `python/large`, `typescript/small`, `typescript/medium`, `typescript/large`, `rust/small`, `rust/medium`, `rust/large`, `go/small`, `go/medium`, `go/large`. ### `process` [Section titled “process”](#process) Measures `process()` with `ProcessConfig::all()` vs `ProcessConfig::minimal()`, on Python medium and large fixtures. Shows the cost of enabling all analysis features vs. extracting nothing. ### `text_splitter` [Section titled “text\_splitter”](#text_splitter) Measures `process()` with chunking enabled (`chunk_size = 1000` bytes, Python medium). Shows the overhead of the syntax-aware chunking pass on top of process. ### `language_detection` [Section titled “language\_detection”](#language_detection) Measures the three detection entry points: | Function | Fixture | | ---------------------------------------------------------- | ------------------------- | | `detect_language_from_extension("py")` | extension lookup | | `detect_language_from_path("src/main.rs")` | path → extension → lookup | | `detect_language_from_content("#!/usr/bin/env python3\n")` | shebang scan | All three are near-zero cost (hash table or memchr scan). ## Parsing is serialized process-wide [Section titled “Parsing is serialized process-wide”](#parsing-is-serialized-process-wide) `crates/ts-pack-core/src/parse.rs` holds a process-wide `PARSE_LOCK` (a `static Mutex<()>` at line 12) that every parse acquires before running (line 24). A handful of third-party external scanners keep process-global state, so parser execution is serialized to keep them correct. The practical effect depends on how much work happens *outside* the lock: * `process()` with a **minimal** config reaches only **0.69x** at 8 threads — that is, it is *slower* than single-threaded, because nearly all the work is inside the lock and threads pay contention on top of it. * `process()` with **all** analysis features enabled reaches **5.11x** at 8 threads, because the AST-walking extraction passes run outside the lock and parallelize normally. So: parallelism helps when you enable real extraction work, and hurts when you do not. If you only need raw trees, one thread is usually the fastest configuration. Only 2 of the 371 grammars (`jsonnet` and `properties`) actually require this serialization; the lock is global because it is applied before the grammar is known. ## Reading Criterion output [Section titled “Reading Criterion output”](#reading-criterion-output) Criterion prints mean, standard deviation, and change vs. the previous run. A result like: ```text parse/python/medium time: [ 1.23 µs 1.31 µs 1.41 µs] ``` Means the 95% confidence interval for the mean is 1.23–1.41 µs. On the first run there is no baseline, so criterion does not show a change percentage. ## Comparing across machines [Section titled “Comparing across machines”](#comparing-across-machines) Criterion stores its baselines in `target/criterion/`. Those files do not commit to the repository. To share results, redirect bench output to a file and compare manually, or use [Bencher](https://bencher.dev) for CI-level tracking. ## Profiling [Section titled “Profiling”](#profiling) For detailed profiling, build a benchmark binary in profile mode: ```bash cargo bench -p tree-sitter-language-pack --no-run # Find the binary ls target/release/deps/benchmarks-* # Then run with a profiler, e.g. samply or cargo-flamegraph ``` # Supported Languages > The full list of 371 tree-sitter grammars bundled by tree-sitter-language-pack, with file extensions, source repository, and ABI version. tree-sitter-language-pack supports **371** languages. | Language | Extensions | Repository | ABI | | ------------------ | ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------- | --- | | Abl | `.p`, `.cls`, `.w` | [usagi-coffee/tree-sitter-abl](https://github.com/usagi-coffee/tree-sitter-abl) | 15 | | Abnf | `.abnf` | [grammars/abnf](https://github.com/xberg-io/tree-sitter-language-pack/tree/main/grammars/abnf) (vendored) | 14 | | Actionscript | `.as` | [Rileran/tree-sitter-actionscript](https://github.com/Rileran/tree-sitter-actionscript) | 14 | | Ada | `.ada`, `.adb`, `.ads` | [briot/tree-sitter-ada](https://github.com/briot/tree-sitter-ada) | 14 | | Agda | `.agda` | [tree-sitter/tree-sitter-agda](https://github.com/tree-sitter/tree-sitter-agda) | 14 | | Aiken | `.ak` | [aiken-lang/tree-sitter-aiken](https://github.com/aiken-lang/tree-sitter-aiken) | 14 | | AL | `.al` | [SShadowS/tree-sitter-al](https://github.com/SShadowS/tree-sitter-al) | 15 | | Angular | — | [dlvandenberg/tree-sitter-angular](https://github.com/dlvandenberg/tree-sitter-angular) | 14 | | Apex | `.trigger` | [aheber/tree-sitter-sfapex](https://github.com/aheber/tree-sitter-sfapex) | 14 | | Applescript | `.applescript`, `.scpt` | [waddie/tree-sitter-applescript](https://github.com/waddie/tree-sitter-applescript) | 14 | | Arduino | `.ino` | [ObserverOfTime/tree-sitter-arduino](https://github.com/ObserverOfTime/tree-sitter-arduino) | 14 | | Asciidoc | `.adoc`, `.asciidoc` | [cathaysia/tree-sitter-asciidoc](https://github.com/cathaysia/tree-sitter-asciidoc) | 14 | | ASM | `.s`, `.asm` | [rush-rs/tree-sitter-asm](https://github.com/rush-rs/tree-sitter-asm) | 14 | | Astro | `.astro` | [virchau13/tree-sitter-astro](https://github.com/virchau13/tree-sitter-astro) | 14 | | Avro | `.avdl` | [victorhqc/tree-sitter-apache-avro](https://github.com/victorhqc/tree-sitter-apache-avro) | 14 | | Awk | `.awk` | [Beaglefoot/tree-sitter-awk](https://github.com/Beaglefoot/tree-sitter-awk) | 14 | | Ballerina | `.bal` | [heshanpadmasiri/tree-sitter-ballerina](https://github.com/heshanpadmasiri/tree-sitter-ballerina) | 14 | | Bash | `.sh`, `.bash` | [tree-sitter/tree-sitter-bash](https://github.com/tree-sitter/tree-sitter-bash) | 14 | | Bass | — | [vito/tree-sitter-bass](https://github.com/vito/tree-sitter-bass) | 14 | | Batch | `.bat`, `.cmd` | [davidevofficial/tree-sitter-batch](https://github.com/davidevofficial/tree-sitter-batch) | 14 | | Beancount | `.beancount` | [polarmutex/tree-sitter-beancount](https://github.com/polarmutex/tree-sitter-beancount) | 14 | | Bibtex | `.bib` | [latex-lsp/tree-sitter-bibtex](https://github.com/latex-lsp/tree-sitter-bibtex) | 14 | | Bicep | `.bicep` | [tree-sitter-grammars/tree-sitter-bicep](https://github.com/tree-sitter-grammars/tree-sitter-bicep) | 14 | | Bitbake | `.bb`, `.bbappend`, `.bbclass` | [tree-sitter-grammars/tree-sitter-bitbake](https://github.com/tree-sitter-grammars/tree-sitter-bitbake) | 14 | | Blade | `.blade` | [EmranMR/tree-sitter-blade](https://github.com/EmranMR/tree-sitter-blade) | 14 | | Bpftrace | `.bt` | [sgruszka/tree-sitter-bpftrace](https://github.com/sgruszka/tree-sitter-bpftrace) | 14 | | Brightscript | `.brs` | [ajdelcimmuto/tree-sitter-brightscript](https://github.com/ajdelcimmuto/tree-sitter-brightscript) | 14 | | BSL | `.bsl` | [alkoleft/tree-sitter-bsl](https://github.com/alkoleft/tree-sitter-bsl) | 14 | | C | `.c`, `.h` | [tree-sitter/tree-sitter-c](https://github.com/tree-sitter/tree-sitter-c) | 14 | | C3 | `.c3`, `.c3i`, `.c3t` | [c3lang/tree-sitter-c3](https://github.com/c3lang/tree-sitter-c3) | 14 | | Caddy | `.caddyfile` | [Samonitari/tree-sitter-caddy](https://github.com/Samonitari/tree-sitter-caddy) | 14 | | Cairo | `.cairo` | [tree-sitter-grammars/tree-sitter-cairo](https://github.com/tree-sitter-grammars/tree-sitter-cairo) | 14 | | Cap’n Proto | `.capnp` | [tree-sitter-grammars/tree-sitter-capnp](https://github.com/tree-sitter-grammars/tree-sitter-capnp) | 14 | | Cedar | `.cedar` | [DuskSystems/tree-sitter-cedar](https://github.com/DuskSystems/tree-sitter-cedar) | 14 | | Cedarschema | `.cedarschema` | [DuskSystems/tree-sitter-cedar](https://github.com/DuskSystems/tree-sitter-cedar) | 14 | | Cel | `.cel` | [bufbuild/tree-sitter-cel](https://github.com/bufbuild/tree-sitter-cel) | 14 | | Cfml | `.cfc` | [cfmleditor/tree-sitter-cfml](https://github.com/cfmleditor/tree-sitter-cfml) | 14 | | Chatito | `.chatito` | [tree-sitter-grammars/tree-sitter-chatito](https://github.com/tree-sitter-grammars/tree-sitter-chatito) | 14 | | Chuck | `.ck` | [tymbalodeon/tree-sitter-chuck](https://github.com/tymbalodeon/tree-sitter-chuck) | 14 | | Circom | `.circom` | [Decurity/tree-sitter-circom](https://github.com/Decurity/tree-sitter-circom) | 14 | | Clarity | `.clar` | [xlittlerag/tree-sitter-clarity](https://github.com/xlittlerag/tree-sitter-clarity) | 14 | | Clojure | `.clj`, `.cljs`, `.cljc` | [sogaiu/tree-sitter-clojure](https://github.com/sogaiu/tree-sitter-clojure) | 14 | | Cmake | `.cmake` | [uyha/tree-sitter-cmake](https://github.com/uyha/tree-sitter-cmake) | 14 | | Cobol | `.cobol`, `.cob`, `.cbl` | [nolanlwin/tree-sitter-cobol](https://github.com/nolanlwin/tree-sitter-cobol) | 14 | | Comment | — | [stsewd/tree-sitter-comment](https://github.com/stsewd/tree-sitter-comment) | 14 | | Commonlisp | `.lisp`, `.cl` | [theHamsta/tree-sitter-commonlisp](https://github.com/theHamsta/tree-sitter-commonlisp) | 14 | | Cooklang | `.cook` | [addcninblue/tree-sitter-cooklang](https://github.com/addcninblue/tree-sitter-cooklang) | 14 | | Corn | `.corn` | [jakestanger/tree-sitter-corn](https://github.com/jakestanger/tree-sitter-corn) | 14 | | Cpon | `.cpon` | [tree-sitter-grammars/tree-sitter-cpon](https://github.com/tree-sitter-grammars/tree-sitter-cpon) | 14 | | Cpp | `.cpp`, `.cxx`, `.cc`, `.hpp`, `.hxx` | [tree-sitter/tree-sitter-cpp](https://github.com/tree-sitter/tree-sitter-cpp) | 15 | | Crystal | `.cr` | [keidax/tree-sitter-crystal](https://github.com/keidax/tree-sitter-crystal) | 14 | | Csharp | `.cs` | [tree-sitter/tree-sitter-c-sharp](https://github.com/tree-sitter/tree-sitter-c-sharp) | 15 | | CSS | `.css` | [tree-sitter/tree-sitter-css](https://github.com/tree-sitter/tree-sitter-css) | 14 | | Cst | `.cst` | [tree-sitter-grammars/tree-sitter-cst](https://github.com/tree-sitter-grammars/tree-sitter-cst) | 14 | | CSV | `.csv` | [amaanq/tree-sitter-csv](https://github.com/amaanq/tree-sitter-csv) | 14 | | CUDA | `.cu`, `.cuda` | [tree-sitter-grammars/tree-sitter-cuda](https://github.com/tree-sitter-grammars/tree-sitter-cuda) | 14 | | Cue | `.cue` | [eonpatapon/tree-sitter-cue](https://github.com/eonpatapon/tree-sitter-cue) | 14 | | Cylc | `.cylc` | [elliotfontaine/tree-sitter-cylc](https://github.com/elliotfontaine/tree-sitter-cylc) | 14 | | Cypher | `.cypher`, `.cql` | [taekwombo/tree-sitter-cypher](https://github.com/taekwombo/tree-sitter-cypher) | 14 | | Cython | `.pyx`, `.pxd`, `.pxi` | [b0o/tree-sitter-cython](https://github.com/b0o/tree-sitter-cython) | 14 | | D | `.d` | [gdamore/tree-sitter-d](https://github.com/gdamore/tree-sitter-d) | 14 | | D2 | `.d2` | [ravsii/tree-sitter-d2](https://github.com/ravsii/tree-sitter-d2) | 14 | | Dart | `.dart` | [UserNobody14/tree-sitter-dart](https://github.com/UserNobody14/tree-sitter-dart) | 14 | | Desktop | `.desktop` | [ValdezFOmar/tree-sitter-desktop](https://github.com/ValdezFOmar/tree-sitter-desktop) | 14 | | Devicetree | `.dts`, `.dtsi` | [joelspadin/tree-sitter-devicetree](https://github.com/joelspadin/tree-sitter-devicetree) | 14 | | Dhall | `.dhall` | [jbellerb/tree-sitter-dhall](https://github.com/jbellerb/tree-sitter-dhall) | 14 | | Diff | `.diff`, `.patch` | [tree-sitter-grammars/tree-sitter-diff](https://github.com/tree-sitter-grammars/tree-sitter-diff) | 14 | | Djot | `.dj` | [treeman/tree-sitter-djot](https://github.com/treeman/tree-sitter-djot) | 14 | | Dockerfile | `.dockerfile` | [camdencheek/tree-sitter-dockerfile](https://github.com/camdencheek/tree-sitter-dockerfile) | 14 | | Dot | `.dot`, `.gv` | [rydesun/tree-sitter-dot](https://github.com/rydesun/tree-sitter-dot) | 14 | | Dotenv | — | [pnx/tree-sitter-dotenv](https://github.com/pnx/tree-sitter-dotenv) | 14 | | Doxygen | — | [tree-sitter-grammars/tree-sitter-doxygen](https://github.com/tree-sitter-grammars/tree-sitter-doxygen) | 14 | | DTD | `.dtd` | [tree-sitter-grammars/tree-sitter-xml](https://github.com/tree-sitter-grammars/tree-sitter-xml) | 14 | | Earthfile | — | [glehmann/tree-sitter-earthfile](https://github.com/glehmann/tree-sitter-earthfile) | 14 | | Ebnf | `.ebnf` | [RubixDev/ebnf](https://github.com/RubixDev/ebnf) | 14 | | Editorconfig | — | [ValdezFOmar/tree-sitter-editorconfig](https://github.com/ValdezFOmar/tree-sitter-editorconfig) | 14 | | Edoc | `.edoc` | [the-mikedavis/tree-sitter-edoc](https://github.com/the-mikedavis/tree-sitter-edoc) | 14 | | Eds | `.eds` | [uyha/tree-sitter-eds](https://github.com/uyha/tree-sitter-eds) | 14 | | Eex | `.eex`, `.leex` | [connorlay/tree-sitter-eex](https://github.com/connorlay/tree-sitter-eex) | 14 | | Eiffel | `.e` | [imustafin/tree-sitter-eiffel](https://github.com/imustafin/tree-sitter-eiffel) | 14 | | Elixir | `.ex`, `.exs` | [elixir-lang/tree-sitter-elixir](https://github.com/elixir-lang/tree-sitter-elixir) | 14 | | Elm | `.elm` | [razzeee/tree-sitter-elm](https://github.com/razzeee/tree-sitter-elm) | 14 | | Elsa | `.lc` | [glapa-grossklag/tree-sitter-elsa](https://github.com/glapa-grossklag/tree-sitter-elsa) | 14 | | Elvish | `.elv` | [elves/tree-sitter-elvish](https://github.com/elves/tree-sitter-elvish) | 14 | | Emacs Lisp | `.el` | [Wilfred/tree-sitter-elisp](https://github.com/Wilfred/tree-sitter-elisp) | 14 | | Embeddedtemplate | `.erb` | [tree-sitter/tree-sitter-embedded-template](https://github.com/tree-sitter/tree-sitter-embedded-template) | 14 | | Enforce | `.enforce` | [simonvic/tree-sitter-enforce](https://github.com/simonvic/tree-sitter-enforce) | 14 | | Erlang | `.erl`, `.hrl` | [WhatsApp/tree-sitter-erlang](https://github.com/WhatsApp/tree-sitter-erlang) | 14 | | F# | `.fs`, `.fsx` | [ionide/tree-sitter-fsharp](https://github.com/ionide/tree-sitter-fsharp) | 15 | | Facility | `.fsd` | [FacilityApi/tree-sitter-facility](https://github.com/FacilityApi/tree-sitter-facility) | 14 | | Faust | `.dsp` | [khiner/tree-sitter-faust](https://github.com/khiner/tree-sitter-faust) | 14 | | Fennel | `.fnl` | [TravonteD/tree-sitter-fennel](https://github.com/TravonteD/tree-sitter-fennel) | 14 | | Fidl | `.fidl` | [google/tree-sitter-fidl](https://github.com/google/tree-sitter-fidl) | 14 | | Firrtl | `.fir` | [tree-sitter-grammars/tree-sitter-firrtl](https://github.com/tree-sitter-grammars/tree-sitter-firrtl) | 14 | | Fish | `.fish` | [ram02z/tree-sitter-fish](https://github.com/ram02z/tree-sitter-fish) | 14 | | Flatbuffers | `.fbs` | [yuanchenxi95/tree-sitter-flatbuffers](https://github.com/yuanchenxi95/tree-sitter-flatbuffers) | 14 | | Fluent | `.ftl` | [tree-sitter/tree-sitter-fluent](https://github.com/tree-sitter/tree-sitter-fluent) | 14 | | Foam | — | [FoamScience/tree-sitter-foam](https://github.com/FoamScience/tree-sitter-foam) | 14 | | Forth | `.fth`, `.4th` | [AlexanderBrevig/tree-sitter-forth](https://github.com/AlexanderBrevig/tree-sitter-forth) | 14 | | Fortran | `.f90`, `.f95`, `.f03`, `.f08`, `.f` | [stadelmanma/tree-sitter-fortran](https://github.com/stadelmanma/tree-sitter-fortran) | 15 | | Fsharp Signature | `.fsi` | [ionide/tree-sitter-fsharp](https://github.com/ionide/tree-sitter-fsharp) | 14 | | Func | `.fc` | [tree-sitter-grammars/tree-sitter-func](https://github.com/tree-sitter-grammars/tree-sitter-func) | 14 | | Fusion | `.fusion` | [jirgn/tree-sitter-fusion](https://gitlab.com/jirgn/tree-sitter-fusion) | 14 | | Gap | `.g`, `.gi` | [gap-system/tree-sitter-gap](https://github.com/gap-system/tree-sitter-gap) | 14 | | Gcode | `.gcode`, `.gco`, `.ngc`, `.nc`, `.tap`, `.cnc` | [ChocolateNao/tree-sitter-gcode](https://github.com/ChocolateNao/tree-sitter-gcode) | 14 | | Gdscript | `.gd` | [PrestonKnopp/tree-sitter-gdscript](https://github.com/PrestonKnopp/tree-sitter-gdscript) | 14 | | Gdshader | `.gdshader` | [airblast-dev/tree-sitter-gdshader](https://github.com/airblast-dev/tree-sitter-gdshader) | 14 | | Gherkin | `.feature` | [SamyAB/tree-sitter-gherkin](https://github.com/SamyAB/tree-sitter-gherkin) | 14 | | Git Config | — | [the-mikedavis/tree-sitter-git-config](https://github.com/the-mikedavis/tree-sitter-git-config) | 14 | | Git Rebase | — | [the-mikedavis/tree-sitter-git-rebase](https://github.com/the-mikedavis/tree-sitter-git-rebase) | 14 | | gitattributes | `.gitattributes` | [ObserverOfTime/tree-sitter-gitattributes](https://github.com/ObserverOfTime/tree-sitter-gitattributes) | 14 | | gitcommit | — | [gbprod/tree-sitter-gitcommit](https://github.com/gbprod/tree-sitter-gitcommit) | 14 | | gitignore | `.gitignore` | [shunsambongi/tree-sitter-gitignore](https://github.com/shunsambongi/tree-sitter-gitignore) | 14 | | Gleam | `.gleam` | [gleam-lang/tree-sitter-gleam](https://github.com/gleam-lang/tree-sitter-gleam) | 14 | | Glimmer | `.hbs` | [ember-tooling/tree-sitter-glimmer](https://github.com/ember-tooling/tree-sitter-glimmer) | 14 | | GLSL | `.glsl` | [theHamsta/tree-sitter-glsl](https://github.com/theHamsta/tree-sitter-glsl) | 14 | | GN | `.gn`, `.gni` | [tree-sitter-grammars/tree-sitter-gn](https://github.com/tree-sitter-grammars/tree-sitter-gn) | 14 | | gnuplot | `.gp`, `.gnuplot`, `.plt` | [dpezto/tree-sitter-gnuplot](https://github.com/dpezto/tree-sitter-gnuplot) | 15 | | Go | `.go` | [tree-sitter/tree-sitter-go](https://github.com/tree-sitter/tree-sitter-go) | 14 | | Godot Resource | `.tres`, `.tscn` | [PrestonKnopp/tree-sitter-godot-resource](https://github.com/PrestonKnopp/tree-sitter-godot-resource) | 14 | | Gomod | `.mod` | [camdencheek/tree-sitter-go-mod](https://github.com/camdencheek/tree-sitter-go-mod) | 14 | | Gosum | — | [tree-sitter-grammars/tree-sitter-go-sum](https://github.com/tree-sitter-grammars/tree-sitter-go-sum) | 14 | | Gotmpl | `.gotmpl` | [ngalaiko/tree-sitter-go-template](https://github.com/ngalaiko/tree-sitter-go-template) | 14 | | Gowork | — | [omertuc/tree-sitter-go-work](https://github.com/omertuc/tree-sitter-go-work) | 14 | | Gpg | — | [tree-sitter-grammars/tree-sitter-gpg-config](https://github.com/tree-sitter-grammars/tree-sitter-gpg-config) | 14 | | Graphql | `.graphql`, `.gql` | [grammars/graphql](https://github.com/xberg-io/tree-sitter-language-pack/tree/main/grammars/graphql) (vendored) | 14 | | Gren | `.gren` | [gren-lang/tree-sitter-gren](https://github.com/gren-lang/tree-sitter-gren) | 14 | | Groovy | `.groovy`, `.gradle` | [Decodetalkers/tree-sitter-groovy](https://github.com/Decodetalkers/tree-sitter-groovy) | 14 | | Gstlaunch | — | [tree-sitter-grammars/tree-sitter-gstlaunch](https://github.com/tree-sitter-grammars/tree-sitter-gstlaunch) | 14 | | Hack | `.hack` | [slackhq/tree-sitter-hack](https://github.com/slackhq/tree-sitter-hack) | 14 | | Haml | `.haml` | [vitallium/tree-sitter-haml](https://github.com/vitallium/tree-sitter-haml) | 14 | | Hare | `.hare` | [tree-sitter-grammars/tree-sitter-hare](https://github.com/tree-sitter-grammars/tree-sitter-hare) | 14 | | Haskell | `.hs` | [tree-sitter/tree-sitter-haskell](https://github.com/tree-sitter/tree-sitter-haskell) | 14 | | Haskell Persistent | — | [MercuryTechnologies/tree-sitter-haskell-persistent](https://github.com/MercuryTechnologies/tree-sitter-haskell-persistent) | 14 | | Haxe | `.hx` | [vantreeseba/tree-sitter-haxe](https://github.com/vantreeseba/tree-sitter-haxe) | 15 | | HCL | `.hcl` | [MichaHoffmann/tree-sitter-hcl](https://github.com/MichaHoffmann/tree-sitter-hcl) | 14 | | Heex | `.heex` | [phoenixframework/tree-sitter-heex](https://github.com/phoenixframework/tree-sitter-heex) | 14 | | Hjson | `.hjson` | [winston0410/tree-sitter-hjson](https://github.com/winston0410/tree-sitter-hjson) | 14 | | HLSL | `.hlsl` | [theHamsta/tree-sitter-hlsl](https://github.com/theHamsta/tree-sitter-hlsl) | 14 | | Hocon | `.hocon` | [antosha417/tree-sitter-hocon](https://github.com/antosha417/tree-sitter-hocon) | 14 | | Hoon | `.hoon` | [urbit-pilled/tree-sitter-hoon](https://github.com/urbit-pilled/tree-sitter-hoon) | 14 | | HTML | `.html`, `.htm` | [tree-sitter/tree-sitter-html](https://github.com/tree-sitter/tree-sitter-html) | 14 | | Htmldjango | — | [interdependence/tree-sitter-htmldjango](https://github.com/interdependence/tree-sitter-htmldjango) | 14 | | HTTP | `.http` | [rest-nvim/tree-sitter-http](https://github.com/rest-nvim/tree-sitter-http) | 14 | | Hurl | `.hurl` | [pfeiferj/tree-sitter-hurl](https://github.com/pfeiferj/tree-sitter-hurl) | 14 | | Hyprlang | — | [tree-sitter-grammars/tree-sitter-hyprlang](https://github.com/tree-sitter-grammars/tree-sitter-hyprlang) | 14 | | Idl | `.idl` | [cathaysia/tree-sitter-idl](https://github.com/cathaysia/tree-sitter-idl) | 14 | | Idris | `.idr` | [kayhide/tree-sitter-idris](https://github.com/kayhide/tree-sitter-idris) | 14 | | Ini | `.ini`, `.cfg` | [justinmk/tree-sitter-ini](https://github.com/justinmk/tree-sitter-ini) | 14 | | Ispc | `.ispc` | [tree-sitter-grammars/tree-sitter-ispc](https://github.com/tree-sitter-grammars/tree-sitter-ispc) | 14 | | Jai | `.jai` | [constantitus/tree-sitter-jai](https://github.com/constantitus/tree-sitter-jai) | 15 | | Janet | `.janet` | [GrayJack/tree-sitter-janet](https://github.com/GrayJack/tree-sitter-janet) | 14 | | Java | `.java` | [tree-sitter/tree-sitter-java](https://github.com/tree-sitter/tree-sitter-java) | 14 | | Javadoc | — | [rmuir/tree-sitter-javadoc](https://github.com/rmuir/tree-sitter-javadoc) | 14 | | JavaScript | `.js`, `.jsx`, `.mjs`, `.cjs` | [tree-sitter/tree-sitter-javascript](https://github.com/tree-sitter/tree-sitter-javascript) | 14 | | Jinja2 | `.j2`, `.jinja2` | [dbt-labs/tree-sitter-jinja2](https://github.com/dbt-labs/tree-sitter-jinja2) | 14 | | Jjdescription | `.jjdescription` | [ribru17/tree-sitter-jjdescription](https://github.com/ribru17/tree-sitter-jjdescription) | 14 | | Jq | `.jq` | [flurie/tree-sitter-jq](https://github.com/flurie/tree-sitter-jq) | 14 | | Jsdoc | — | [tree-sitter/tree-sitter-jsdoc](https://github.com/tree-sitter/tree-sitter-jsdoc) | 14 | | JSON | `.json` | [tree-sitter/tree-sitter-json](https://github.com/tree-sitter/tree-sitter-json) | 14 | | JSON5 | `.json5` | [Joakker/tree-sitter-json5](https://github.com/Joakker/tree-sitter-json5) | 14 | | Jsonnet | `.jsonnet`, `.libsonnet` | [sourcegraph/tree-sitter-jsonnet](https://github.com/sourcegraph/tree-sitter-jsonnet) | 14 | | Julia | `.jl` | [tree-sitter/tree-sitter-julia](https://github.com/tree-sitter/tree-sitter-julia) | 14 | | Just | `.just` | [casey/tree-sitter-just](https://github.com/casey/tree-sitter-just) | 14 | | Kcl | `.k` | [kcl-lang/tree-sitter-kcl](https://github.com/kcl-lang/tree-sitter-kcl) | 14 | | Kconfig | — | [tree-sitter-grammars/tree-sitter-kconfig](https://github.com/tree-sitter-grammars/tree-sitter-kconfig) | 14 | | KDL | `.kdl` | [tree-sitter-grammars/tree-sitter-kdl](https://github.com/tree-sitter-grammars/tree-sitter-kdl) | 14 | | Kitty | — | [OXY2DEV/tree-sitter-kitty](https://github.com/OXY2DEV/tree-sitter-kitty) | 14 | | Koka | `.kk` | [koka-community/tree-sitter-koka](https://github.com/koka-community/tree-sitter-koka) | 14 | | Kotlin | `.kt`, `.kts` | [fwcd/tree-sitter-kotlin](https://github.com/fwcd/tree-sitter-kotlin) | 14 | | Koto | `.koto` | [koto-lang/tree-sitter-koto](https://github.com/koto-lang/tree-sitter-koto) | 14 | | Kusto | `.kql` | [Willem-J-an/tree-sitter-kusto](https://github.com/Willem-J-an/tree-sitter-kusto) | 14 | | Lalrpop | `.lalrpop` | [traxys/tree-sitter-lalrpop](https://github.com/traxys/tree-sitter-lalrpop) | 14 | | LaTeX | `.tex` | [latex-lsp/tree-sitter-latex](https://github.com/latex-lsp/tree-sitter-latex) | 14 | | Lean | `.lean` | [Julian/tree-sitter-lean](https://github.com/Julian/tree-sitter-lean) | 15 | | Ledger | `.ldg`, `.ledger`, `.journal` | [cbarrete/tree-sitter-ledger](https://github.com/cbarrete/tree-sitter-ledger) | 14 | | Leo | `.leo` | [r001/tree-sitter-leo](https://github.com/r001/tree-sitter-leo) | 14 | | Less | `.less` | [rhino1998/tree-sitter-less](https://github.com/rhino1998/tree-sitter-less) | 14 | | Linkerscript | `.lds` | [tree-sitter-grammars/tree-sitter-linkerscript](https://github.com/tree-sitter-grammars/tree-sitter-linkerscript) | 14 | | Liquid | `.liquid` | [hankthetank27/tree-sitter-liquid](https://github.com/hankthetank27/tree-sitter-liquid) | 14 | | LLVM | `.ll` | [benwilliamgraham/tree-sitter-llvm](https://github.com/benwilliamgraham/tree-sitter-llvm) | 14 | | Llvm Mir | `.mir` | [Flakebi/tree-sitter-llvm-mir](https://github.com/Flakebi/tree-sitter-llvm-mir) | 14 | | Lua | `.lua` | [MunifTanjim/tree-sitter-lua](https://github.com/MunifTanjim/tree-sitter-lua) | 14 | | Luadoc | — | [tree-sitter-grammars/tree-sitter-luadoc](https://github.com/tree-sitter-grammars/tree-sitter-luadoc) | 14 | | Luap | — | [tree-sitter-grammars/tree-sitter-luap](https://github.com/tree-sitter-grammars/tree-sitter-luap) | 14 | | Luau | `.luau` | [tree-sitter-grammars/tree-sitter-luau](https://github.com/tree-sitter-grammars/tree-sitter-luau) | 14 | | M68k | — | [grahambates/tree-sitter-m68k](https://github.com/grahambates/tree-sitter-m68k) | 14 | | Magik | `.magik` | [krn-robin/tree-sitter-magik](https://github.com/krn-robin/tree-sitter-magik) | 14 | | Make | `.mk`, `.makefile` | [alemuller/tree-sitter-make](https://github.com/alemuller/tree-sitter-make) | 14 | | Markdown | `.md`, `.markdown` | [tree-sitter-grammars/tree-sitter-markdown](https://github.com/tree-sitter-grammars/tree-sitter-markdown) | 14 | | Markdown Inline | — | [tree-sitter-grammars/tree-sitter-markdown](https://github.com/tree-sitter-grammars/tree-sitter-markdown) | 14 | | MATLAB | `.matlab` | [acristoffers/tree-sitter-matlab](https://github.com/acristoffers/tree-sitter-matlab) | 14 | | Menhir | `.mly` | [Kerl13/tree-sitter-menhir](https://github.com/Kerl13/tree-sitter-menhir) | 14 | | Mermaid | `.mmd`, `.mermaid` | [monaqa/tree-sitter-mermaid](https://github.com/monaqa/tree-sitter-mermaid) | 14 | | Meson | `.meson` | [Decodetalkers/tree-sitter-meson](https://github.com/Decodetalkers/tree-sitter-meson) | 14 | | Mlir | `.mlir` | [artagnon/tree-sitter-mlir](https://github.com/artagnon/tree-sitter-mlir) | 14 | | Mojo | `.mojo` | [HerringtonDarkholme/tree-sitter-mojo](https://github.com/HerringtonDarkholme/tree-sitter-mojo) | 14 | | Moonbit | `.mbt`, `.mbti` | [moonbitlang/tree-sitter-moonbit](https://github.com/moonbitlang/tree-sitter-moonbit) | 14 | | Motoko | `.mo` | [polychromatist/tree-sitter-motoko](https://github.com/polychromatist/tree-sitter-motoko) | 14 | | Move | `.move` | [tree-sitter-grammars/tree-sitter-move](https://github.com/tree-sitter-grammars/tree-sitter-move) | 14 | | NASM | `.nasm` | [naclsn/tree-sitter-nasm](https://github.com/naclsn/tree-sitter-nasm) | 14 | | Netlinx | `.axs`, `.axi` | [Norgate-AV/tree-sitter-netlinx](https://github.com/Norgate-AV/tree-sitter-netlinx) | 14 | | nginx | `.conf`, `.nginx` | [opa-oz/tree-sitter-nginx](https://github.com/opa-oz/tree-sitter-nginx) | 14 | | Nickel | `.ncl` | [nickel-lang/tree-sitter-nickel](https://github.com/nickel-lang/tree-sitter-nickel) | 14 | | Nim | `.nim`, `.nims` | [aMOPel/tree-sitter-nim](https://github.com/aMOPel/tree-sitter-nim) | 14 | | Ninja | `.ninja` | [alemuller/tree-sitter-ninja](https://github.com/alemuller/tree-sitter-ninja) | 14 | | Nix | `.nix` | [nix-community/tree-sitter-nix](https://github.com/nix-community/tree-sitter-nix) | 14 | | Norg | `.norg` | [nvim-neorg/tree-sitter-norg](https://github.com/nvim-neorg/tree-sitter-norg) | 14 | | Norg Meta | — | [nvim-neorg/tree-sitter-norg-meta](https://github.com/nvim-neorg/tree-sitter-norg-meta) | 14 | | Nqc | `.nqc` | [tree-sitter-grammars/tree-sitter-nqc](https://github.com/tree-sitter-grammars/tree-sitter-nqc) | 14 | | Nushell | `.nu` | [nushell/tree-sitter-nu](https://github.com/nushell/tree-sitter-nu) | 14 | | Objc | `.m` | [tree-sitter-grammars/tree-sitter-objc](https://github.com/tree-sitter-grammars/tree-sitter-objc) | 14 | | OCaml | `.ml` | [tree-sitter/tree-sitter-ocaml](https://github.com/tree-sitter/tree-sitter-ocaml) | 14 | | OCaml Interface | `.mli` | [tree-sitter/tree-sitter-ocaml](https://github.com/tree-sitter/tree-sitter-ocaml) | 14 | | Ocamllex | `.mll` | [atom-ocaml/tree-sitter-ocamllex](https://github.com/atom-ocaml/tree-sitter-ocamllex) | 14 | | Odin | `.odin` | [tree-sitter-grammars/tree-sitter-odin](https://github.com/tree-sitter-grammars/tree-sitter-odin) | 14 | | Openscad | `.scad` | [bollian/tree-sitter-openscad](https://github.com/bollian/tree-sitter-openscad) | 14 | | Org | `.org` | [milisims/tree-sitter-org](https://github.com/milisims/tree-sitter-org) | 14 | | Pascal | `.pas` | [Isopod/tree-sitter-pascal](https://github.com/Isopod/tree-sitter-pascal) | 14 | | Pem | `.pem` | [tree-sitter-grammars/tree-sitter-pem](https://github.com/tree-sitter-grammars/tree-sitter-pem) | 14 | | Penrose | `.style`, `.substance`, `.domain` | [klukaszek/tree-sitter-penrose](https://github.com/klukaszek/tree-sitter-penrose) | 14 | | Perl | `.pl`, `.pm` | [tree-sitter-perl/tree-sitter-perl](https://github.com/tree-sitter-perl/tree-sitter-perl) | 15 | | PGN | `.pgn` | [rolandwalker/tree-sitter-pgn](https://github.com/rolandwalker/tree-sitter-pgn) | 14 | | PHP | `.php` | [tree-sitter/tree-sitter-php](https://github.com/tree-sitter/tree-sitter-php) | 14 | | Phpdoc | — | [claytonrcarter/tree-sitter-phpdoc](https://github.com/claytonrcarter/tree-sitter-phpdoc) | 14 | | Picat | `.pi`, `.picat` | [dlr-ft/tree-sitter-picat](https://github.com/dlr-ft/tree-sitter-picat) | 14 | | Pkl | `.pkl` | [apple/tree-sitter-pkl](https://github.com/apple/tree-sitter-pkl) | 14 | | Plantuml | `.puml`, `.plantuml`, `.iuml` | [grammars/plantuml](https://github.com/xberg-io/tree-sitter-language-pack/tree/main/grammars/plantuml) (vendored) | 14 | | PO | `.po`, `.pot` | [tree-sitter-grammars/tree-sitter-po](https://github.com/tree-sitter-grammars/tree-sitter-po) | 14 | | Poe Filter | `.filter` | [tree-sitter-grammars/tree-sitter-poe-filter](https://github.com/tree-sitter-grammars/tree-sitter-poe-filter) | 14 | | Pony | `.pony` | [tree-sitter-grammars/tree-sitter-pony](https://github.com/tree-sitter-grammars/tree-sitter-pony) | 14 | | Postgres | `.psql`, `.pgsql` | [gmr/tree-sitter-postgres](https://github.com/gmr/tree-sitter-postgres) | 15 | | Postscript | `.ps`, `.eps` | [smoeding/tree-sitter-postscript](https://github.com/smoeding/tree-sitter-postscript) | 14 | | Powershell | `.ps1`, `.psm1`, `.psd1` | [airbus-cert/tree-sitter-powershell](https://github.com/airbus-cert/tree-sitter-powershell) | 14 | | Printf | — | [tree-sitter-grammars/tree-sitter-printf](https://github.com/tree-sitter-grammars/tree-sitter-printf) | 14 | | Prisma | `.prisma` | [LumaKernel/tree-sitter-prisma](https://github.com/LumaKernel/tree-sitter-prisma) | 14 | | Prolog | `.pro` | [Rukiza/tree-sitter-prolog](https://github.com/Rukiza/tree-sitter-prolog) | 14 | | Promela | `.pml` | [grammars/promela](https://github.com/xberg-io/tree-sitter-language-pack/tree/main/grammars/promela) (vendored) | 14 | | Promql | `.promql` | [MichaHoffmann/tree-sitter-promql](https://github.com/MichaHoffmann/tree-sitter-promql) | 14 | | Properties | `.properties` | [tree-sitter-grammars/tree-sitter-properties](https://github.com/tree-sitter-grammars/tree-sitter-properties) | 14 | | Protocol Buffers | `.proto` | [coder3101/tree-sitter-proto](https://github.com/coder3101/tree-sitter-proto) | 14 | | Prql | `.prql` | [PRQL/tree-sitter-prql](https://github.com/PRQL/tree-sitter-prql) | 14 | | PSV | `.psv` | [amaanq/tree-sitter-csv](https://github.com/amaanq/tree-sitter-csv) | 14 | | Pug | `.pug` | [zealot128/tree-sitter-pug](https://github.com/zealot128/tree-sitter-pug) | 14 | | Puppet | `.pp` | [tree-sitter-grammars/tree-sitter-puppet](https://github.com/tree-sitter-grammars/tree-sitter-puppet) | 14 | | PureScript | `.purs` | [postsolar/tree-sitter-purescript](https://github.com/postsolar/tree-sitter-purescript) | 14 | | Pymanifest | — | [tree-sitter-grammars/tree-sitter-pymanifest](https://github.com/tree-sitter-grammars/tree-sitter-pymanifest) | 14 | | Python | `.py`, `.pyi`, `.pyw` | [tree-sitter/tree-sitter-python](https://github.com/tree-sitter/tree-sitter-python) | 14 | | QL | `.ql` | [tree-sitter/tree-sitter-ql](https://github.com/tree-sitter/tree-sitter-ql) | 14 | | QML | `.qml` | [yuja/tree-sitter-qmljs](https://github.com/yuja/tree-sitter-qmljs) | 14 | | Qmldir | — | [tree-sitter-grammars/tree-sitter-qmldir](https://github.com/tree-sitter-grammars/tree-sitter-qmldir) | 14 | | Query | — | [tree-sitter-grammars/tree-sitter-query](https://github.com/tree-sitter-grammars/tree-sitter-query) | 14 | | R | `.r` | [r-lib/tree-sitter-r](https://github.com/r-lib/tree-sitter-r) | 14 | | Racket | `.rkt` | [6cdh/tree-sitter-racket](https://github.com/6cdh/tree-sitter-racket) | 14 | | Rasi | `.rasi` | [Fymyte/tree-sitter-rasi](https://github.com/Fymyte/tree-sitter-rasi) | 14 | | Razor | `.razor`, `.cshtml` | [tris203/tree-sitter-razor](https://github.com/tris203/tree-sitter-razor) | 15 | | RBS | `.rbs` | [joker1007/tree-sitter-rbs](https://github.com/joker1007/tree-sitter-rbs) | 14 | | re2c | `.re` | [tree-sitter-grammars/tree-sitter-re2c](https://github.com/tree-sitter-grammars/tree-sitter-re2c) | 14 | | Readline | — | [tree-sitter-grammars/tree-sitter-readline](https://github.com/tree-sitter-grammars/tree-sitter-readline) | 14 | | Reason | `.rei` | [grammars/reason](https://github.com/xberg-io/tree-sitter-language-pack/tree/main/grammars/reason) (vendored) | 14 | | Regex | — | [tree-sitter/tree-sitter-regex](https://github.com/tree-sitter/tree-sitter-regex) | 14 | | Rego | `.rego` | [FallenAngel97/tree-sitter-rego](https://github.com/FallenAngel97/tree-sitter-rego) | 14 | | Requirements | — | [tree-sitter-grammars/tree-sitter-requirements](https://github.com/tree-sitter-grammars/tree-sitter-requirements) | 14 | | Rescript | `.res`, `.resi` | [rescript-lang/tree-sitter-rescript](https://github.com/rescript-lang/tree-sitter-rescript) | 14 | | reStructuredText | `.rst` | [stsewd/tree-sitter-rst](https://github.com/stsewd/tree-sitter-rst) | 14 | | Robot | `.robot` | [Hubro/tree-sitter-robot](https://github.com/Hubro/tree-sitter-robot) | 14 | | Roc | `.roc` | [faldor20/tree-sitter-roc](https://github.com/faldor20/tree-sitter-roc) | 14 | | Ron | `.ron` | [tree-sitter-grammars/tree-sitter-ron](https://github.com/tree-sitter-grammars/tree-sitter-ron) | 14 | | Rshtml | — | [rshtml/tree-sitter-rshtml](https://github.com/rshtml/tree-sitter-rshtml) | 14 | | Rtf | `.rtf` | [GoodNotes/tree-sitter-rtf](https://github.com/GoodNotes/tree-sitter-rtf) | 14 | | Ruby | `.rb` | [tree-sitter/tree-sitter-ruby](https://github.com/tree-sitter/tree-sitter-ruby) | 14 | | Rust | `.rs` | [tree-sitter/tree-sitter-rust](https://github.com/tree-sitter/tree-sitter-rust) | 14 | | Sas | `.sas` | [ix-infrastructure/tree-sitter-sas](https://github.com/ix-infrastructure/tree-sitter-sas) | 14 | | Scala | `.scala` | [tree-sitter/tree-sitter-scala](https://github.com/tree-sitter/tree-sitter-scala) | 15 | | Scfg | `.scfg` | [rockorager/tree-sitter-scfg](https://github.com/rockorager/tree-sitter-scfg) | 14 | | Scheme | `.scm` | [6cdh/tree-sitter-scheme](https://github.com/6cdh/tree-sitter-scheme) | 14 | | SCSS | `.scss` | [tree-sitter-grammars/tree-sitter-scss](https://github.com/tree-sitter-grammars/tree-sitter-scss) | 14 | | Sflog | `.sflog` | [aheber/tree-sitter-sfapex](https://github.com/aheber/tree-sitter-sfapex) | 14 | | Slang | `.slang` | [tree-sitter-grammars/tree-sitter-slang](https://github.com/tree-sitter-grammars/tree-sitter-slang) | 15 | | Slim | `.slim` | [kolen/tree-sitter-slim](https://github.com/kolen/tree-sitter-slim) | 14 | | Slint | `.slint` | [slint-ui/tree-sitter-slint](https://github.com/slint-ui/tree-sitter-slint) | 14 | | Smali | `.smali` | [tree-sitter-grammars/tree-sitter-smali](https://github.com/tree-sitter-grammars/tree-sitter-smali) | 14 | | Smalltalk | `.st` | [tom95/tree-sitter-smalltalk](https://github.com/tom95/tree-sitter-smalltalk) | 14 | | Smithy | `.smithy` | [indoorvivants/tree-sitter-smithy](https://github.com/indoorvivants/tree-sitter-smithy) | 14 | | Sml | `.sml`, `.sig`, `.fun` | [MatthewFluet/tree-sitter-sml](https://github.com/MatthewFluet/tree-sitter-sml) | 14 | | Snakemake | `.smk` | [osthomas/tree-sitter-snakemake](https://github.com/osthomas/tree-sitter-snakemake) | 14 | | Snl | `.stt` | [minijackson/tree-sitter-snl](https://github.com/minijackson/tree-sitter-snl) | 14 | | Solidity | `.sol` | [JoranHonig/tree-sitter-solidity](https://github.com/JoranHonig/tree-sitter-solidity) | 14 | | Soql | `.soql` | [aheber/tree-sitter-sfapex](https://github.com/aheber/tree-sitter-sfapex) | 14 | | Sosl | `.sosl` | [aheber/tree-sitter-sfapex](https://github.com/aheber/tree-sitter-sfapex) | 14 | | Souffle | `.dl` | [langston-barrett/tree-sitter-souffle](https://github.com/langston-barrett/tree-sitter-souffle) | 14 | | Sourcepawn | `.sp`, `.inc` | [nilshelmig/tree-sitter-sourcepawn](https://github.com/nilshelmig/tree-sitter-sourcepawn) | 14 | | Sparql | `.sparql` | [GordianDziwis/tree-sitter-sparql](https://github.com/GordianDziwis/tree-sitter-sparql) | 14 | | Spicedb | `.zed` | [jzelinskie/tree-sitter-spicedb](https://github.com/jzelinskie/tree-sitter-spicedb) | 14 | | SQL | `.sql` | [DerekStride/tree-sitter-sql](https://github.com/DerekStride/tree-sitter-sql) | 14 | | Sql Bigquery | `.bq` | [takegue/tree-sitter-sql-bigquery](https://github.com/takegue/tree-sitter-sql-bigquery) | 14 | | Squirrel | `.squirrel`, `.nut` | [tree-sitter-grammars/tree-sitter-squirrel](https://github.com/tree-sitter-grammars/tree-sitter-squirrel) | 14 | | Ssh Config | — | [ObserverOfTime/tree-sitter-ssh-config](https://github.com/ObserverOfTime/tree-sitter-ssh-config) | 14 | | Stan | `.stan` | [WardBrian/tree-sitter-stan](https://github.com/WardBrian/tree-sitter-stan) | 14 | | Starlark | `.star`, `.bzl` | [tree-sitter-grammars/tree-sitter-starlark](https://github.com/tree-sitter-grammars/tree-sitter-starlark) | 14 | | Strace | `.strace` | [sigmaSd/tree-sitter-strace](https://github.com/sigmaSd/tree-sitter-strace) | 14 | | Styled | — | [mskelton/tree-sitter-styled](https://github.com/mskelton/tree-sitter-styled) | 14 | | Superhtml | `.shtml` | [kristoff-it/superhtml](https://github.com/kristoff-it/superhtml) | 14 | | Svelte | `.svelte` | [Himujjal/tree-sitter-svelte](https://github.com/Himujjal/tree-sitter-svelte) | 14 | | Sway | `.sw` | [FuelLabs/tree-sitter-sway](https://github.com/FuelLabs/tree-sitter-sway) | 14 | | Swift | `.swift` | [alex-pinkus/tree-sitter-swift](https://github.com/alex-pinkus/tree-sitter-swift) | 14 | | Sxhkdrc | `.sxhkdrc` | [RaafatTurki/tree-sitter-sxhkdrc](https://github.com/RaafatTurki/tree-sitter-sxhkdrc) | 14 | | Sysml | `.sysml` | [nomograph/tree-sitter-sysml](https://gitlab.com/nomograph/tree-sitter-sysml) | 14 | | Systemtap | `.stp`, `.stpm` | [ok-ryoko/tree-sitter-systemtap](https://github.com/ok-ryoko/tree-sitter-systemtap) | 14 | | Systemverilog | `.sv`, `.svh` | [gmlarumbe/tree-sitter-systemverilog](https://github.com/gmlarumbe/tree-sitter-systemverilog) | 15 | | T32 | `.cmm`, `.cmmt`, `.t32` | [xasc/tree-sitter-t32](https://github.com/xasc/tree-sitter-t32) | 14 | | Tablegen | `.td` | [Flakebi/tree-sitter-tablegen](https://github.com/Flakebi/tree-sitter-tablegen) | 14 | | Tact | `.tact` | [tact-lang/tree-sitter-tact](https://github.com/tact-lang/tree-sitter-tact) | 14 | | Task | `.task` | [alexanderbrevig/tree-sitter-task](https://github.com/alexanderbrevig/tree-sitter-task) | 14 | | Tcl | `.tcl` | [lewis6991/tree-sitter-tcl](https://github.com/lewis6991/tree-sitter-tcl) | 14 | | Teal | `.tl` | [euclidianAce/tree-sitter-teal](https://github.com/euclidianAce/tree-sitter-teal) | 14 | | Templ | `.templ` | [vrischmann/tree-sitter-templ](https://github.com/vrischmann/tree-sitter-templ) | 14 | | Tera | `.tera` | [uncenter/tree-sitter-tera](https://github.com/uncenter/tree-sitter-tera) | 14 | | Terraform | `.tf`, `.tfvars` | [tree-sitter-grammars/tree-sitter-hcl](https://github.com/tree-sitter-grammars/tree-sitter-hcl) | 14 | | Test | — | [tree-sitter-grammars/tree-sitter-test](https://github.com/tree-sitter-grammars/tree-sitter-test) | 14 | | Textproto | `.textproto`, `.pbtxt` | [PorterAtGoogle/tree-sitter-textproto](https://github.com/PorterAtGoogle/tree-sitter-textproto) | 14 | | Thrift | `.thrift` | [tree-sitter-grammars/tree-sitter-thrift](https://github.com/tree-sitter-grammars/tree-sitter-thrift) | 14 | | Tlaplus | `.tla` | [tlaplus-community/tree-sitter-tlaplus](https://github.com/tlaplus-community/tree-sitter-tlaplus) | 14 | | Tmux | — | [Freed-Wu/tree-sitter-tmux](https://github.com/Freed-Wu/tree-sitter-tmux) | 14 | | Todotxt | `.todotxt` | [arnarg/tree-sitter-todotxt](https://github.com/arnarg/tree-sitter-todotxt) | 14 | | TOML | `.toml` | [tree-sitter-grammars/tree-sitter-toml](https://github.com/tree-sitter-grammars/tree-sitter-toml) | 14 | | Tsql | — | [Crary-Systems/tree-sitter-tsql](https://github.com/Crary-Systems/tree-sitter-tsql) | 14 | | TSV | `.tsv` | [amaanq/tree-sitter-csv](https://github.com/amaanq/tree-sitter-csv) | 14 | | TSX | `.tsx` | [tree-sitter/tree-sitter-typescript](https://github.com/tree-sitter/tree-sitter-typescript) | 14 | | Turtle | `.ttl` | [GordianDziwis/tree-sitter-turtle](https://github.com/GordianDziwis/tree-sitter-turtle) | 14 | | Twig | `.twig` | [gbprod/tree-sitter-twig](https://github.com/gbprod/tree-sitter-twig) | 14 | | TypeScript | `.ts`, `.mts`, `.cts` | [tree-sitter/tree-sitter-typescript](https://github.com/tree-sitter/tree-sitter-typescript) | 14 | | Typespec | `.tsp` | [happenslol/tree-sitter-typespec](https://github.com/happenslol/tree-sitter-typespec) | 14 | | Typoscript | `.typoscript`, `.tsconfig` | [Teddytrombone/tree-sitter-typoscript](https://github.com/Teddytrombone/tree-sitter-typoscript) | 14 | | Typst | `.typst` | [uben0/tree-sitter-typst](https://github.com/uben0/tree-sitter-typst) | 14 | | udev | — | [tree-sitter-grammars/tree-sitter-udev](https://github.com/tree-sitter-grammars/tree-sitter-udev) | 14 | | Ungrammar | — | [tree-sitter-grammars/tree-sitter-ungrammar](https://github.com/tree-sitter-grammars/tree-sitter-ungrammar) | 14 | | Unison | `.u` | [kylegoetz/tree-sitter-unison](https://github.com/kylegoetz/tree-sitter-unison) | 14 | | Uxntal | `.tal` | [tree-sitter-grammars/tree-sitter-uxntal](https://github.com/tree-sitter-grammars/tree-sitter-uxntal) | 14 | | V | `.v` | [nedpals/tree-sitter-v](https://github.com/nedpals/tree-sitter-v) | 14 | | Vala | `.vala`, `.vapi` | [matbme/tree-sitter-vala](https://github.com/matbme/tree-sitter-vala) | 14 | | Vb | `.vb` | [CodeAnt-AI/tree-sitter-vb-dotnet](https://github.com/CodeAnt-AI/tree-sitter-vb-dotnet) | 14 | | Vento | `.vto` | [ventojs/tree-sitter-vento](https://github.com/ventojs/tree-sitter-vento) | 14 | | Verilog | `.verilog` | [tree-sitter/tree-sitter-verilog](https://github.com/tree-sitter/tree-sitter-verilog) | 14 | | VHDL | `.vhdl`, `.vhd` | [alemuller/tree-sitter-vhdl](https://github.com/alemuller/tree-sitter-vhdl) | 14 | | Vhs | `.tape` | [charmbracelet/tree-sitter-vhs](https://github.com/charmbracelet/tree-sitter-vhs) | 14 | | Vim | `.vim` | [tree-sitter-grammars/tree-sitter-vim](https://github.com/tree-sitter-grammars/tree-sitter-vim) | 14 | | Vimdoc | `.txt` | [neovim/tree-sitter-vimdoc](https://github.com/neovim/tree-sitter-vimdoc) | 14 | | Vrl | `.vrl` | [belltoy/tree-sitter-vrl](https://github.com/belltoy/tree-sitter-vrl) | 14 | | Vue | `.vue` | [tree-sitter-grammars/tree-sitter-vue](https://github.com/tree-sitter-grammars/tree-sitter-vue) | 14 | | Wast | `.wast` | [mkatychev/tree-sitter-wasm](https://github.com/mkatychev/tree-sitter-wasm) | 14 | | Wat | `.wat` | [mkatychev/tree-sitter-wasm](https://github.com/mkatychev/tree-sitter-wasm) | 14 | | Wdl | `.wdl` | [stjude-rust-labs/tree-sitter-wdl](https://github.com/stjude-rust-labs/tree-sitter-wdl) | 14 | | WGSL | `.wgsl` | [szebniok/tree-sitter-wgsl](https://github.com/szebniok/tree-sitter-wgsl) | 14 | | Wgsl Bevy | — | [tree-sitter-grammars/tree-sitter-wgsl-bevy](https://github.com/tree-sitter-grammars/tree-sitter-wgsl-bevy) | 14 | | Wit | `.wit` | [bytecodealliance/tree-sitter-wit](https://github.com/bytecodealliance/tree-sitter-wit) | 14 | | Wolfram | `.wl`, `.wls` | [grammars/wolfram](https://github.com/xberg-io/tree-sitter-language-pack/tree/main/grammars/wolfram) (vendored) | 14 | | X86asm | — | [bearcove/tree-sitter-x86asm](https://github.com/bearcove/tree-sitter-x86asm) | 14 | | Xcompose | — | [tree-sitter-grammars/tree-sitter-xcompose](https://github.com/tree-sitter-grammars/tree-sitter-xcompose) | 14 | | Xit | `.xit` | [synaptiko/tree-sitter-xit](https://github.com/synaptiko/tree-sitter-xit) | 14 | | XML | `.xml`, `.xsl`, `.xslt` | [tree-sitter-grammars/tree-sitter-xml](https://github.com/tree-sitter-grammars/tree-sitter-xml) | 14 | | Xquery | `.xq`, `.xqy`, `.xquery` | [grammars/xquery](https://github.com/xberg-io/tree-sitter-language-pack/tree/main/grammars/xquery) (vendored) | 14 | | Xresources | `.xresources`, `.xdefaults` | [ValdezFOmar/tree-sitter-xresources](https://github.com/ValdezFOmar/tree-sitter-xresources) | 14 | | YAML | `.yaml`, `.yml` | [tree-sitter-grammars/tree-sitter-yaml](https://github.com/tree-sitter-grammars/tree-sitter-yaml) | 14 | | Yang | `.yang` | [Hubro/tree-sitter-yang](https://github.com/Hubro/tree-sitter-yang) | 14 | | Yuck | `.yuck` | [tree-sitter-grammars/tree-sitter-yuck](https://github.com/tree-sitter-grammars/tree-sitter-yuck) | 14 | | Yul | `.yul` | [grammars/yul](https://github.com/xberg-io/tree-sitter-language-pack/tree/main/grammars/yul) (vendored) | 14 | | Zig | `.zig` | [maxxnino/tree-sitter-zig](https://github.com/maxxnino/tree-sitter-zig) | 14 | | Ziggy | `.ziggy` | [kristoff-it/ziggy](https://github.com/kristoff-it/ziggy) | 14 | | Ziggy Schema | — | [kristoff-it/ziggy](https://github.com/kristoff-it/ziggy) | 14 | | Zsh | `.zsh` | [georgeharker/tree-sitter-zsh](https://github.com/georgeharker/tree-sitter-zsh) | 15 | ## ABI Compatibility [Section titled “ABI Compatibility”](#abi-compatibility) The pack ships parsers at tree-sitter ABI 14. These load on any consumer tree-sitter runtime from 0.21 through 0.26, so `get_language` passthrough works with a bring-your-own-runtime setup across that range. The following grammars ship at a higher ABI because their committed `parser.c` is too large to regenerate. They require tree-sitter >=0.25: * Abl (ABI 15) * AL (ABI 15) * Cpp (ABI 15) * Csharp (ABI 15) * F# (ABI 15) * Fortran (ABI 15) * gnuplot (ABI 15) * Haxe (ABI 15) * Jai (ABI 15) * Lean (ABI 15) * Perl (ABI 15) * Postgres (ABI 15) * Razor (ABI 15) * Scala (ABI 15) * Slang (ABI 15) * Systemverilog (ABI 15) * Zsh (ABI 15) # C API Reference ## C API Reference v1.16.1 [Section titled “C API Reference v1.16.1”](#c-api-reference-v1161) ### Functions [Section titled “Functions”](#functions) #### ts\_pack\_detect\_language\_from\_extension() [Section titled “ts\_pack\_detect\_language\_from\_extension()”](#ts_pack_detect_language_from_extension) Detect language name from a file extension (without leading dot). Returns `NULL` for unrecognized extensions. The match is case-insensitive. **Signature:** ```c const char* ts_pack_detect_language_from_extension(const char* ext); ``` **Example:** ```c const char* result = ts_pack_detect_language_from_extension("value"); ``` **Parameters:** | Name | Type | Required | Description | | ----- | ------------- | -------- | ----------- | | `ext` | `const char*` | Yes | The ext | **Returns:** `const char*` *** #### ts\_pack\_detect\_language\_from\_path() [Section titled “ts\_pack\_detect\_language\_from\_path()”](#ts_pack_detect_language_from_path) Detect language name from a file path. Extracts the file extension and looks it up. Returns `NULL` if the path has no extension or the extension is not recognized. **Signature:** ```c const char* ts_pack_detect_language_from_path(const char* path); ``` **Example:** ```c const char* result = ts_pack_detect_language_from_path("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------- | -------- | ---------------- | | `path` | `const char*` | Yes | Path to the file | **Returns:** `const char*` *** #### ts\_pack\_detect\_language\_from\_content() [Section titled “ts\_pack\_detect\_language\_from\_content()”](#ts_pack_detect_language_from_content) Detect language name from file content using the shebang line (`#!`). Inspects only the first line of `content`. If it begins with `#!`, the interpreter name is extracted and mapped to a language name. Handles common patterns: * `#!/usr/bin/env python3` → `"python"` * `#!/bin/bash` → `"bash"` * `#!/usr/bin/env node` → `"javascript"` The `-S` flag accepted by some `env` implementations is skipped automatically. Version suffixes (e.g. `python3.11`, `ruby3.2`) are stripped before matching. A leading UTF-8 BOM (`U+FEFF`) is skipped before the `#!` check, so a BOM-prefixed script is still detected by its shebang. Returns `NULL` when content does not start with `#!` (after stripping a leading BOM), the shebang is malformed, or the interpreter is not recognised. **Signature:** ```c const char* ts_pack_detect_language_from_content(const char* content); ``` **Example:** ```c const char* result = ts_pack_detect_language_from_content("value"); ``` **Parameters:** | Name | Type | Required | Description | | --------- | ------------- | -------- | ---------------------- | | `content` | `const char*` | Yes | The content to process | **Returns:** `const char*` *** #### ts\_pack\_get\_highlights\_query() [Section titled “ts\_pack\_get\_highlights\_query()”](#ts_pack_get_highlights_query) Get the highlights query for a language, if bundled. Returns the contents of `highlights.scm` as a static string, or `NULL` if no highlights query is bundled for this language. **Signature:** ```c const char* ts_pack_get_highlights_query(const char* language); ``` **Example:** ```c const char* result = ts_pack_get_highlights_query("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------------- | -------- | ------------ | | `language` | `const char*` | Yes | The language | **Returns:** `const char*` *** #### ts\_pack\_get\_injections\_query() [Section titled “ts\_pack\_get\_injections\_query()”](#ts_pack_get_injections_query) Get the injections query for a language, if bundled. Returns the contents of `injections.scm` as a static string, or `NULL` if no injections query is bundled for this language. **Signature:** ```c const char* ts_pack_get_injections_query(const char* language); ``` **Example:** ```c const char* result = ts_pack_get_injections_query("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------------- | -------- | ------------ | | `language` | `const char*` | Yes | The language | **Returns:** `const char*` *** #### ts\_pack\_get\_locals\_query() [Section titled “ts\_pack\_get\_locals\_query()”](#ts_pack_get_locals_query) Get the locals query for a language, if bundled. Returns the contents of `locals.scm` as a static string, or `NULL` if no locals query is bundled for this language. **Signature:** ```c const char* ts_pack_get_locals_query(const char* language); ``` **Example:** ```c const char* result = ts_pack_get_locals_query("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------------- | -------- | ------------ | | `language` | `const char*` | Yes | The language | **Returns:** `const char*` *** #### ts\_pack\_get\_tags\_query() [Section titled “ts\_pack\_get\_tags\_query()”](#ts_pack_get_tags_query) Get the tags query for a language, if bundled. Returns the contents of `tags.scm` as a static string, or `NULL` if no tags query is bundled for this language. **Signature:** ```c const char* ts_pack_get_tags_query(const char* language); ``` **Example:** ```c const char* result = ts_pack_get_tags_query("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------------- | -------- | ------------ | | `language` | `const char*` | Yes | The language | **Returns:** `const char*` *** #### ts\_pack\_get\_indents\_query() [Section titled “ts\_pack\_get\_indents\_query()”](#ts_pack_get_indents_query) Get the indents query for a language, if bundled. Returns the contents of `indents.scm` (used for auto-indentation) as a static string, or `NULL` if no indents query is bundled for this language. **Signature:** ```c const char* ts_pack_get_indents_query(const char* language); ``` **Example:** ```c const char* result = ts_pack_get_indents_query("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------------- | -------- | ------------ | | `language` | `const char*` | Yes | The language | **Returns:** `const char*` *** #### ts\_pack\_get\_folds\_query() [Section titled “ts\_pack\_get\_folds\_query()”](#ts_pack_get_folds_query) Get the folds query for a language, if bundled. Returns the contents of `folds.scm` (used for code folding) as a static string, or `NULL` if no folds query is bundled for this language. **Signature:** ```c const char* ts_pack_get_folds_query(const char* language); ``` **Example:** ```c const char* result = ts_pack_get_folds_query("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------------- | -------- | ------------ | | `language` | `const char*` | Yes | The language | **Returns:** `const char*` *** #### ts\_pack\_get\_language() [Section titled “ts\_pack\_get\_language()”](#ts_pack_get_language) Get a tree-sitter `Language` by name using the global registry. Resolves language aliases (e.g., `"shell"` maps to `"bash"`). When the `download` feature is enabled (default), automatically downloads the parser from GitHub releases if not found locally. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.Download` if auto-download fails. **Signature:** ```c TS_PACKAlefHandle ts_pack_get_language(const char* name); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_get_language("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------- | -------- | ----------- | | `name` | `const char*` | Yes | The name | **Returns:** `TS_PACKAlefHandle` **Errors:** Returns the sentinel handle `0` on error. *** #### ts\_pack\_get\_parser() [Section titled “ts\_pack\_get\_parser()”](#ts_pack_get_parser) Get a `Parser` pre-configured for the given language. This is a convenience function that calls `get_language` and configures a new parser in one step. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language cannot be applied to the parser. **Signature:** ```c TS_PACKAlefHandle ts_pack_get_parser(const char* name); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_get_parser("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------- | -------- | ----------- | | `name` | `const char*` | Yes | The name | **Returns:** `TS_PACKAlefHandle` **Errors:** Returns the sentinel handle `0` on error. *** #### ts\_pack\_detect\_language() [Section titled “ts\_pack\_detect\_language()”](#ts_pack_detect_language) Detect language name from a file path or extension. This compatibility alias matches the pre-Alef Python binding API. **Signature:** ```c const char* ts_pack_detect_language(const char* path); ``` **Example:** ```c const char* result = ts_pack_detect_language("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------- | -------- | ---------------- | | `path` | `const char*` | Yes | Path to the file | **Returns:** `const char*` *** #### ts\_pack\_available\_languages() [Section titled “ts\_pack\_available\_languages()”](#ts_pack_available_languages) List all available language names (sorted, deduplicated, includes aliases). Returns names of both statically compiled and dynamically loadable languages, plus any configured aliases. **Signature:** ```c const char* ts_pack_available_languages(); ``` **Example:** ```c const char* result = ts_pack_available_languages(); ``` **Returns:** `const char*` *** #### ts\_pack\_has\_language() [Section titled “ts\_pack\_has\_language()”](#ts_pack_has_language) Check if a language is available by name or alias. Returns `true` if the language can be loaded (statically compiled, dynamically available, or a known alias for one of these). **Signature:** ```c int32_t ts_pack_has_language(const char* name); ``` **Example:** ```c int32_t result = ts_pack_has_language("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------- | -------- | ----------- | | `name` | `const char*` | Yes | The name | **Returns:** `int32_t` *** #### ts\_pack\_language\_count() [Section titled “ts\_pack\_language\_count()”](#ts_pack_language_count) Return the number of available languages. Includes statically compiled languages, dynamically loadable languages, and aliases. **Signature:** ```c uintptr_t ts_pack_language_count(); ``` **Example:** ```c uintptr_t result = ts_pack_language_count(); ``` **Returns:** `uintptr_t` *** #### ts\_pack\_process() [Section titled “ts\_pack\_process()”](#ts_pack_process) Process source code and extract file intelligence using the global registry. Parses the source with tree-sitter and extracts metrics, structure, imports, exports, comments, docstrings, symbols, diagnostics, and/or chunks based on the flags set in `ProcessConfig`. **Errors:** Returns `Error.InvalidRange` if the config carries a zero-valued limit or the source exceeds `ProcessConfig.max_source_bytes`, `Error.ParseTimeout` if the parse exceeds `ProcessConfig.parse_timeout_ms`, `Error.LanguageNotFound` if the language is unknown, or `Error.ParseFailed` if parsing yields no tree. **Signature:** ```c TS_PACKAlefHandle ts_pack_process(const char* source, TS_PACKAlefHandle config); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_process("value", 0); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------------- | -------- | ------------------------- | | `source` | `const char*` | Yes | The source | | `config` | `TS_PACKAlefHandle` | Yes | The configuration options | **Returns:** `TS_PACKAlefHandle` **Errors:** Returns the sentinel handle `0` on error. *** #### ts\_pack\_init() [Section titled “ts\_pack\_init()”](#ts_pack_init) Initialize the language pack with the given configuration. Applies any custom cache directory, then downloads all languages and groups specified in the config. This is the recommended entry point when you want to pre-warm the cache before use. **Errors:** Returns an error if configuration cannot be applied or if downloads fail. **Signature:** ```c int32_t ts_pack_init(TS_PACKAlefHandle config); ``` **Example:** ```c ts_pack_init(0); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------------- | -------- | ------------------------- | | `config` | `TS_PACKAlefHandle` | Yes | The configuration options | **Returns:** `int32_t` status code – `0` on success, `-1` on error. **Errors:** Returns `-1` on error. *** #### ts\_pack\_configure() [Section titled “ts\_pack\_configure()”](#ts_pack_configure) Apply download configuration without downloading anything. Use this to set a custom cache directory before the first call to `get_language` or any download function. Changing the cache dir after languages have been registered has no effect on already-loaded languages. `PackConfig.cache_dir` is a BASE directory, not the final libs path: this crate appends `tree-sitter-language-pack/v{version}/libs` to it, the same suffix applied to the platform default cache directory. In the example below, files actually land under `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`, never directly in `/tmp/my-parsers/`. Call `cache_dir` to read back the resolved, fully-suffixed path. **Errors:** Returns an error if the lock cannot be acquired. **Signature:** ```c int32_t ts_pack_configure(TS_PACKAlefHandle config); ``` **Example:** ```c ts_pack_configure(0); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------------- | -------- | ------------------------- | | `config` | `TS_PACKAlefHandle` | Yes | The configuration options | **Returns:** `int32_t` status code – `0` on success, `-1` on error. **Errors:** Returns `-1` on error. *** #### ts\_pack\_download() [Section titled “ts\_pack\_download()”](#ts_pack_download) Download specific languages to the local cache. Returns the number of distinct languages available after the call. Already compiled or cached languages are included in the count. Aliases are resolved before counting, so `["shell", "bash"]` names one language and returns 1. **Errors:** Returns an error if any language is not available in the manifest or if the download fails. **Signature:** ```c uintptr_t ts_pack_download(const char* names); ``` **Example:** ```c uintptr_t result = ts_pack_download(NULL); ``` **Parameters:** | Name | Type | Required | Description | | ------- | ------------- | -------- | ----------- | | `names` | `const char*` | Yes | The names | **Returns:** `uintptr_t` **Errors:** Returns `0` on error. *** #### ts\_pack\_prefetch() [Section titled “ts\_pack\_prefetch()”](#ts_pack_prefetch) Prefetch grammars: download any not already loadable from disk, then load every requested language into the process registry so a subsequent hot loop only parses. Unlike `download()`, this does not trust in-memory availability — it downloads whenever a grammar is not actually loadable from disk (fixing the case where a known-but-not-downloaded grammar is reported present), then resolves and caches every requested language. Call it once, up front, before a parallel workload. **Errors:** Returns `Error.Download` if a required grammar cannot be fetched, or `Error.LanguageNotFound` if a requested name is unknown. **Signature:** ```c int32_t ts_pack_prefetch(const char* languages); ``` **Example:** ```c ts_pack_prefetch(NULL); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | ------------- | -------- | ------------- | | `languages` | `const char*` | Yes | The languages | **Returns:** `int32_t` status code – `0` on success, `-1` on error. **Errors:** Returns `-1` on error. *** #### ts\_pack\_download\_all() [Section titled “ts\_pack\_download\_all()”](#ts_pack_download_all) Download all available languages from the remote manifest. Downloads the platform bundle and extracts every library it contains. Languages that appear in the manifest but are absent from the bundle (e.g. grammars that failed to compile at release time) are silently skipped — they are not treated as an error. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns an error if the manifest cannot be fetched or the bundle download fails. **Signature:** ```c uintptr_t ts_pack_download_all(); ``` **Example:** ```c uintptr_t result = ts_pack_download_all(); ``` **Returns:** `uintptr_t` **Errors:** Returns `0` on error. *** #### ts\_pack\_download\_group() [Section titled “ts\_pack\_download\_group()”](#ts_pack_download_group) Download every language in a named group. Groups are defined by the remote manifest, not by this library, and let you ensure a curated set of related grammars in one call instead of listing each name to `download()`. Already-cached languages are skipped. Call `manifest_groups` to discover the group names the manifest actually defines. The published manifest currently defines a single group, `"all"`; earlier revisions of this documentation advertised `"web"`, `"data"`, and `"systems"`, which the manifest has never contained, so every call following that example failed. Do not hardcode a group name without checking. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns `Error.Download` if the manifest cannot be fetched, if the group is unknown — the message lists the groups the manifest defines — or if any constituent language fails to download. **Signature:** ```c uintptr_t ts_pack_download_group(const char* name); ``` **Example:** ```c uintptr_t result = ts_pack_download_group("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------- | -------- | ----------- | | `name` | `const char*` | Yes | The name | **Returns:** `uintptr_t` **Errors:** Returns `0` on error. *** #### ts\_pack\_manifest\_languages() [Section titled “ts\_pack\_manifest\_languages()”](#ts_pack_manifest_languages) Return all language names available in the remote manifest (371). Fetches (and caches) the remote manifest to discover the full list of downloadable languages. Use `downloaded_languages` to list what is already cached locally. **Errors:** Returns an error if the manifest cannot be fetched. **Signature:** ```c const char* ts_pack_manifest_languages(); ``` **Example:** ```c const char* result = ts_pack_manifest_languages(); ``` **Returns:** `const char*` **Errors:** Returns `NULL` on error. *** #### ts\_pack\_manifest\_groups() [Section titled “ts\_pack\_manifest\_groups()”](#ts_pack_manifest_groups) Return the names of every language group the remote manifest defines, sorted. Group names are manifest data, not a compile-time constant of this library, so this is the only reliable way to learn what `download_group` and `PackConfig.groups` accept. The published manifest currently defines just `"all"`. **Errors:** Returns `Error.Download` if the manifest cannot be fetched. **Signature:** ```c const char* ts_pack_manifest_groups(); ``` **Example:** ```c const char* result = ts_pack_manifest_groups(); ``` **Returns:** `const char*` **Errors:** Returns `NULL` on error. *** #### ts\_pack\_downloaded\_languages() [Section titled “ts\_pack\_downloaded\_languages()”](#ts_pack_downloaded_languages) Return languages that are already downloaded and cached locally. Does not perform any network requests. Returns an empty list if the cache directory does not exist or cannot be read. **Signature:** ```c const char* ts_pack_downloaded_languages(); ``` **Example:** ```c const char* result = ts_pack_downloaded_languages(); ``` **Returns:** `const char*` *** #### ts\_pack\_clean\_cache() [Section titled “ts\_pack\_clean\_cache()”](#ts_pack_clean_cache) Delete all cached parser shared libraries. Resets the cache registration so the next call to `get_language` or a download function will re-register the (now empty) cache directory. **Errors:** Returns an error if the cache directory cannot be removed. **Signature:** ```c int32_t ts_pack_clean_cache(); ``` **Example:** ```c ts_pack_clean_cache(); ``` **Returns:** `int32_t` status code – `0` on success, `-1` on error. **Errors:** Returns `-1` on error. *** #### ts\_pack\_cache\_dir() [Section titled “ts\_pack\_cache\_dir()”](#ts_pack_cache_dir) Return the effective cache directory path. This is `{base}/tree-sitter-language-pack/v{version}/libs/`, where `{base}` is either the custom BASE directory set via `configure` / `init` (`PackConfig.cache_dir`) or the platform default cache directory — both are suffixed identically, so a custom `cache_dir` is never used as the final libs path. The default resolves to `~/.cache/tree-sitter-language-pack/v{version}/libs/` on a typical Unix system. **Errors:** Returns an error if no cache directory can be resolved: `version` is somehow invalid, or (with no custom `cache_dir` configured) the platform reports none and `TREE_SITTER_LANGUAGE_PACK_CACHE_DIR` is unset. This crate no longer falls back to the temporary directory for the latter case — see #101 H2. **Signature:** ```c const char* ts_pack_cache_dir(); ``` **Example:** ```c const char *result = ts_pack_cache_dir(); ``` **Returns:** `const char*` **Errors:** Returns `NULL` on error. *** ### Types [Section titled “Types”](#types) #### TS\_PACKByteRange [Section titled “TS\_PACKByteRange”](#ts_packbyterange) **C representation:** `TS_PACKByteRange` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKByteRange` does not appear anywhere in the generated header. A byte range — start (inclusive) to end (exclusive). | Field | Type | Default | Description | | ------- | ----------- | ------- | ---------------------------- | | `start` | `uintptr_t` | — | Inclusive start byte offset. | | `end` | `uintptr_t` | — | Exclusive end byte offset. | *** #### TS\_PACKChunkContext [Section titled “TS\_PACKChunkContext”](#ts_packchunkcontext) **C representation:** `TS_PACKChunkContext` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKChunkContext` does not appear anywhere in the generated header. Metadata for a single chunk of source code. | Field | Type | Default | Description | | ----------------- | ------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `const char*` | — | Language name used to parse this chunk. | | `chunk_index` | `uintptr_t` | — | Zero-indexed position of this chunk within the file’s chunk list. | | `total_chunks` | `uintptr_t` | — | Total number of chunks the file was split into. | | `node_types` | `const char*` | `NULL` | Tree-sitter node kinds that appear at the top level of this chunk. | | `context_path` | `const char*` | `NULL` | Hierarchical path of enclosing structural items (e.g., `["MyClass", "my_method"]`). | | `symbols_defined` | `const char*` | `NULL` | Names of symbols defined within this chunk. | | `comments` | `const char*` | `NULL` | Comments contained within this chunk. | | `docstrings` | `const char*` | `NULL` | Docstrings contained within this chunk. Populated only for Python — the same language for which `ProcessResult.docstrings` is populated, and by the same classifier. Always empty for every other language. | | `has_error_nodes` | `int32_t` | — | Whether this chunk contains any tree-sitter error nodes. | *** #### TS\_PACKCodeChunk [Section titled “TS\_PACKCodeChunk”](#ts_packcodechunk) **C representation:** `TS_PACKCodeChunk` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKCodeChunk` does not appear anywhere in the generated header. A chunk of source code with rich metadata. | Field | Type | Default | Description | | ------------ | ------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `content` | `const char*` | — | The raw source text of this chunk. | | `start_byte` | `uintptr_t` | — | Inclusive start byte offset of this chunk in the original source. | | `end_byte` | `uintptr_t` | — | Exclusive end byte offset of this chunk in the original source. | | `start_line` | `uintptr_t` | — | Zero-indexed start line of this chunk. | | `end_line` | `uintptr_t` | — | Zero-indexed row of the last byte actually included in this chunk (inclusive — the same row a `Span.end_line` would report for a node ending on that byte). Computed the same way regardless of whether the source has a trailing newline: it is always the row of `end_byte - 1`, never a phantom row past the file’s real content. | | `metadata` | `TS_PACKAlefHandle` | — | Contextual metadata about this chunk. | *** #### TS\_PACKCommentInfo [Section titled “TS\_PACKCommentInfo”](#ts_packcommentinfo) **C representation:** `TS_PACKCommentInfo` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKCommentInfo` does not appear anywhere in the generated header. A comment extracted from source code. | Field | Type | Default | Description | | ----------------- | ------------------- | -------------- | ----------------------------------------------------------------- | | `text` | `const char*` | — | The raw text content of the comment. | | `kind` | `TS_PACKAlefHandle` | `TS_PACK_LINE` | The kind of comment (line, block, or doc). | | `span` | `TS_PACKAlefHandle` | — | Source span covering the comment. | | `associated_node` | `const char*` | `NULL` | Name of the syntax node this comment is directly associated with. | *** #### TS\_PACKDataAttribute [Section titled “TS\_PACKDataAttribute”](#ts_packdataattribute) **C representation:** `TS_PACKDataAttribute` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKDataAttribute` does not appear anywhere in the generated header. An XML-style attribute attached to an `Element` node. Populated only for `DataNodeKind.Element`; always empty for `KeyValue` and `Sequence` nodes. | Field | Type | Default | Description | | ------- | ------------------- | ------- | --------------------------------------------------------------- | | `name` | `const char*` | — | Attribute name (e.g. `"class"`, `"href"`). | | `value` | `const char*` | — | Attribute value as a raw string (quotes stripped). | | `span` | `TS_PACKAlefHandle` | — | Source span covering the entire `name="value"` attribute token. | *** #### TS\_PACKDataNode [Section titled “TS\_PACKDataNode”](#ts_packdatanode) **C representation:** `TS_PACKDataNode` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKDataNode` does not appear anywhere in the generated header. A node in the hierarchical data tree produced by data-format extraction. When `ProcessConfig.data_extraction` is `true`, `ProcessResult.data` is populated with a root `DataNode` whose `children` mirror the structure of the parsed file. The `kind` field determines which other fields are meaningful: | `kind` | `key` | `value` | `attributes` | `children` | | ---------- | ------------------------- | ------------ | ------------ | -------------- | | `KeyValue` | key / mapping key / index | leaf value | empty | nested map | | `Element` | XML tag name | text content | XML attrs | child elements | | `Sequence` | positional index (`"0"`) | leaf value | empty | sub-items | | Field | Type | Default | Description | | ------------ | ------------------- | ------------------- | ----------------------------------------------------------------------------------------------------- | | `kind` | `TS_PACKAlefHandle` | `TS_PACK_KEY_VALUE` | Whether this node is a key/value pair, XML element, or sequence item. | | `key` | `const char*` | `NULL` | Key, attribute name, tag name, or positional index (`"0"`, `"1"`, …). `NULL` at the document root. | | `value` | `const char*` | `NULL` | Leaf scalar value, if any. `NULL` for containers (objects, arrays, XML elements with child elements). | | `attributes` | `const char*` | `NULL` | Attributes on element-shape nodes (XML `STag` attributes). Empty for all other kinds. | | `children` | `const char*` | `NULL` | Children for nested containers and XML element bodies. | | `span` | `TS_PACKAlefHandle` | — | Source span covering this node in the original source file. | *** #### TS\_PACKDiagnostic [Section titled “TS\_PACKDiagnostic”](#ts_packdiagnostic) **C representation:** `TS_PACKDiagnostic` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKDiagnostic` does not appear anywhere in the generated header. A diagnostic (syntax error, missing node, etc.) from parsing. | Field | Type | Default | Description | | ---------- | ------------------- | --------------- | ---------------------------------------------- | | `message` | `const char*` | — | Human-readable description of the diagnostic. | | `severity` | `TS_PACKAlefHandle` | `TS_PACK_ERROR` | Severity of the diagnostic. | | `span` | `TS_PACKAlefHandle` | — | Source span where the diagnostic was detected. | *** #### TS\_PACKDocSection [Section titled “TS\_PACKDocSection”](#ts_packdocsection) **C representation:** `TS_PACKDocSection` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKDocSection` does not appear anywhere in the generated header. A section within a docstring (e.g., Args, Returns, Raises). | Field | Type | Default | Description | | ------------- | ------------- | ------- | ------------------------------------------------------- | | `kind` | `const char*` | — | Section kind (e.g., `"args"`, `"returns"`, `"raises"`). | | `name` | `const char*` | `NULL` | Parameter or return value name, if applicable. | | `description` | `const char*` | — | Description text for this section. | *** #### TS\_PACKDocstringInfo [Section titled “TS\_PACKDocstringInfo”](#ts_packdocstringinfo) **C representation:** `TS_PACKDocstringInfo` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKDocstringInfo` does not appear anywhere in the generated header. A docstring extracted from source code. | Field | Type | Default | Description | | ----------------- | ------------------- | ----------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | `const char*` | — | The raw text of the docstring. | | `format` | `TS_PACKAlefHandle` | `TS_PACK_PYTHON_TRIPLE_QUOTE` | The docstring format (Python, JSDoc, Rustdoc, etc.). | | `span` | `TS_PACKAlefHandle` | — | Source span covering the docstring. | | `associated_item` | `const char*` | `NULL` | Name of the item this docstring documents. | | `parsed_sections` | `const char*` | `NULL` | Parsed sections of the docstring (Args, Returns, Raises, etc.). **Reserved: not yet populated.** Always empty, for every `DocstringFormat`. Parsing a docstring body into sections requires implementing each convention’s own layout (Google/NumPy/reST style for Python, `@param`/`@returns` for JSDoc/Javadoc, and so on), which no extractor here does yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | *** #### TS\_PACKDownloadManager [Section titled “TS\_PACKDownloadManager”](#ts_packdownloadmanager) **C representation:** `TS_PACKDownloadManager` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKDownloadManager` does not appear anywhere in the generated header. Manages downloading and caching of pre-built parser shared libraries. ##### Methods [Section titled “Methods”](#methods) ###### ts\_pack\_download\_manager\_new() [Section titled “ts\_pack\_download\_manager\_new()”](#ts_pack_download_manager_new) Create a new download manager for the given version. **Errors:** Returns `Error.Download` if `version` is empty, contains a path separator or `..`, or contains a character outside `[A-Za-z0-9.+-]` — see `validate_version` — or if no cache directory can be resolved (see `Self.default_cache_dir`). **Signature:** ```c TS_PACKAlefHandle ts_pack_download_manager_new(const char* version); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_download_manager_new("value"); ``` **Parameters:** | Name | Type | Required | Description | | --------- | ------------- | -------- | ----------- | | `version` | `const char*` | Yes | The version | **Returns:** `TS_PACKAlefHandle` **Errors:** Returns the sentinel handle `0` on error. ###### ts\_pack\_download\_manager\_installed\_languages() [Section titled “ts\_pack\_download\_manager\_installed\_languages()”](#ts_pack_download_manager_installed_languages) List languages that are already downloaded and cached. Derived from the on-disk cache filenames, one canonical name per file, plus every alias that resolves to it (via `aliases_for`) — so this list agrees with the user-facing `LanguageRegistry.available_languages` about which names are “available”; both report `"shell"` once `bash` is cached, for example. A previous version reported canonical names only, which could never agree with `available_languages()`. See #107. Returns an empty list if the cache directory does not exist. If it exists but cannot be read (e.g. a permission error), also returns an empty list — changing this to a `Result` would be a breaking change across every language binding — but logs a `tracing.warn!` so the failure is not silently indistinguishable from “nothing installed”. **Signature:** ```c const char* ts_pack_download_manager_installed_languages(TS_PACKAlefHandle this); ``` **Example:** ```c const char* result = ts_pack_download_manager_installed_languages(instance); ``` **Returns:** `const char*` ###### ts\_pack\_download\_manager\_download\_all\_best\_effort() [Section titled “ts\_pack\_download\_manager\_download\_all\_best\_effort()”](#ts_pack_download_manager_download_all_best_effort) Download the platform bundle and extract every library file it contains. Unlike `Self.ensure_languages`, this does not check the manifest language list against archive contents — it simply extracts all `.so`/`.dylib`/`.dll` files from the bundle. Languages in the manifest that are missing from the archive are silently ignored rather than returning an error. Returns the number of library files extracted (including those already cached). **Signature:** ```c uintptr_t ts_pack_download_manager_download_all_best_effort(TS_PACKAlefHandle this); ``` **Example:** ```c uintptr_t result = ts_pack_download_manager_download_all_best_effort(instance); ``` **Returns:** `uintptr_t` **Errors:** Returns `0` on error. ###### ts\_pack\_download\_manager\_clean\_cache() [Section titled “ts\_pack\_download\_manager\_clean\_cache()”](#ts_pack_download_manager_clean_cache) Remove all cached parser libraries. Acquires the cross-process lock so `clean_cache` cannot race a concurrent downloader (avoids Windows sharing-violation errors against an in-flight bundle write). The `.download.lock` file itself is **not** removed — it is permanent infrastructure; deleting it could allow a concurrent process that already opened the file to continue holding a stale lock handle while a new process opens a fresh inode, breaking the mutual-exclusion guarantee. **Signature:** ```c int32_t ts_pack_download_manager_clean_cache(TS_PACKAlefHandle this); ``` **Example:** ```c ts_pack_download_manager_clean_cache(instance); ``` **Returns:** `int32_t` status code – `0` on success, `-1` on error. **Errors:** Returns `-1` on error. *** #### TS\_PACKExportInfo [Section titled “TS\_PACKExportInfo”](#ts_packexportinfo) **C representation:** `TS_PACKExportInfo` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKExportInfo` does not appear anywhere in the generated header. An export statement extracted from source code. | Field | Type | Default | Description | | ------ | ------------------- | --------------- | -------------------------------------------------- | | `name` | `const char*` | — | The exported name. | | `kind` | `TS_PACKAlefHandle` | `TS_PACK_NAMED` | The kind of export (named, default, or re-export). | | `span` | `TS_PACKAlefHandle` | — | Source span covering the export statement. | *** #### TS\_PACKFileMetrics [Section titled “TS\_PACKFileMetrics”](#ts_packfilemetrics) **C representation:** `TS_PACKFileMetrics` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKFileMetrics` does not appear anywhere in the generated header. Aggregate metrics for a source file. | Field | Type | Default | Description | | --------------- | ----------- | ------- | -------------------------------------------------------------- | | `total_lines` | `uintptr_t` | — | Total number of lines (including blank and comment lines). | | `code_lines` | `uintptr_t` | — | Number of lines containing non-blank, non-comment source code. | | `comment_lines` | `uintptr_t` | — | Number of lines that are entirely comments. | | `blank_lines` | `uintptr_t` | — | Number of blank (whitespace-only) lines. | | `total_bytes` | `uintptr_t` | — | Total byte length of the source file. | | `node_count` | `uintptr_t` | — | Total number of nodes in the syntax tree. | | `error_count` | `uintptr_t` | — | Number of error nodes in the syntax tree (parse errors). | | `max_depth` | `uintptr_t` | — | Maximum nesting depth reached in the syntax tree. | *** #### TS\_PACKImportInfo [Section titled “TS\_PACKImportInfo”](#ts_packimportinfo) **C representation:** `TS_PACKImportInfo` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKImportInfo` does not appear anywhere in the generated header. An import statement extracted from source code. | Field | Type | Default | Description | | ------------- | ------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `source` | `const char*` | — | The module or path being imported from. | | `items` | `const char*` | `NULL` | Specific names imported from the source module. For `import a, b` / `from m import a, b`, every entry’s base name (never the alias). For a JavaScript/TypeScript named-imports clause (`import { a, b as c } from 'm'`), every specifier’s original name. Populated for Python and JavaScript/TypeScript only. Always empty for every other language this library recognises import statements for — Rust, Go, Java, Kotlin, and Elixir (`import`/`alias`/`require`/`use`) — and for a JS/TS namespace import (`import * as ns`) or default import (`import x from 'm'`), neither of which names individual items. | | `alias` | `const char*` | `NULL` | Alias assigned to the import (e.g., `import numpy as np`). Populated for Python’s single-name form (`import numpy as np`, `from m import a as b`) and JavaScript/TypeScript’s namespace form (`import * as ns from 'm'`) or a named-imports clause naming exactly one specifier (`import { a as b } from 'm'`). `NULL` for Rust, Go, Java, Kotlin, and Elixir (which has its own `as:` alias option on `alias` directives, not yet extracted here) — and for a Python statement that aliases several names at once (`import os, sys as s`), where there is no single alias to report for the statement as a whole, so only `items` is populated for it. | | `is_wildcard` | `int32_t` | — | Whether this is a wildcard import (e.g., `import *` or `use foo.*`). Detected from the syntax tree — a dedicated wildcard node (`wildcard_import` in Python, `use_wildcard` in Rust) or a bare `*` token outside of string-literal content — not by searching the import’s source text for a `*` character, so a glob in an import path string (`import a from './glob*.js'`) is not mistaken for one. | | `span` | `TS_PACKAlefHandle` | — | Source span covering the import statement. | *** #### TS\_PACKLanguage [Section titled “TS\_PACKLanguage”](#ts_packlanguage) **C representation:** `TS_PACKLanguage` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKLanguage` does not appear anywhere in the generated header. *** #### TS\_PACKLanguageRegistry [Section titled “TS\_PACKLanguageRegistry”](#ts_packlanguageregistry) **C representation:** `TS_PACKLanguageRegistry` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKLanguageRegistry` does not appear anywhere in the generated header. Thread-safe registry of tree-sitter language parsers. Manages both statically compiled and dynamically loaded language grammars. Use `LanguageRegistry.new()` for the default registry, or access the global instance via the module-level convenience functions (`get_language`, `available_languages`, etc.). ##### Methods [Section titled “Methods”](#methods-1) ###### ts\_pack\_language\_registry\_new() [Section titled “ts\_pack\_language\_registry\_new()”](#ts_pack_language_registry_new) Create a new registry populated with all statically compiled languages. When the `dynamic-loading` feature is enabled, the registry also knows about dynamically loadable grammars and will load them on demand. **Signature:** ```c TS_PACKAlefHandle ts_pack_language_registry_new(); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_language_registry_new(); ``` **Returns:** `TS_PACKAlefHandle` ###### ts\_pack\_language\_registry\_get\_language() [Section titled “ts\_pack\_language\_registry\_get\_language()”](#ts_pack_language_registry_get_language) Get a tree-sitter `Language` by name. Resolves aliases (e.g., `"shell"` -> `"bash"`, `"makefile"` -> `"make"`), then looks up the language in the static table. When the `dynamic-loading` feature is enabled, falls back to loading a shared library on demand. **Errors:** Returns `Error.LanguageNotFound` if the name (after alias resolution) does not match any known grammar. **Signature:** ```c TS_PACKAlefHandle ts_pack_language_registry_get_language(TS_PACKAlefHandle this, const char* name); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_language_registry_get_language(instance, "value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------- | -------- | ----------- | | `name` | `const char*` | Yes | The name | **Returns:** `TS_PACKAlefHandle` **Errors:** Returns the sentinel handle `0` on error. ###### ts\_pack\_language\_registry\_available\_languages() [Section titled “ts\_pack\_language\_registry\_available\_languages()”](#ts_pack_language_registry_available_languages) List all available language names, sorted and deduplicated. Includes statically compiled languages, dynamically loadable languages (if the `dynamic-loading` feature is enabled), and all configured aliases. **Signature:** ```c const char* ts_pack_language_registry_available_languages(TS_PACKAlefHandle this); ``` **Example:** ```c const char* result = ts_pack_language_registry_available_languages(instance); ``` **Returns:** `const char*` ###### ts\_pack\_language\_registry\_has\_parser() [Section titled “ts\_pack\_language\_registry\_has\_parser()”](#ts_pack_language_registry_has_parser) Check whether this language can be parsed right now, without downloading. Resolves aliases, then answers from exactly the lookup `get_language` performs: the statically compiled table, the already-loaded dynamic grammars, and the parser shared libraries present in the primary and extra (download-cache) library directories. It never performs network I/O. A previous implementation consulted only the statically compiled table. That table is empty in every build that does not set `TSLP_LANGUAGES`, so the function answered `false` for languages this registry parses perfectly well. Contrast `has_language`, which is also `true` for a grammar that is merely *known to the manifest* and would have to be downloaded first. The pair distinguishes “we can parse it offline, now” from “we recognise the name”. The first `true` answer for a dynamic grammar loads its shared library: loading is the only way to know the grammar is usable, since a truncated or wrong-architecture library exists on disk but cannot parse. Loads are cached process-wide, so repeat calls are cheap. **Signature:** ```c int32_t ts_pack_language_registry_has_parser(TS_PACKAlefHandle this, const char* name); ``` **Example:** ```c int32_t result = ts_pack_language_registry_has_parser(instance, "value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------- | -------- | ----------- | | `name` | `const char*` | Yes | The name | **Returns:** `int32_t` ###### ts\_pack\_language\_registry\_has\_language() [Section titled “ts\_pack\_language\_registry\_has\_language()”](#ts_pack_language_registry_has_language) Check whether a language is available by name or alias. Returns `true` if the language can be loaded, either from the static table or from a dynamic library on disk. Every branch is one more way to answer `true`, so they are ordered cheapest-first and the filesystem is only consulted once every in-memory source has said no. Probing the loaded-grammar map and the manifest ahead of the `stat` calls is what keeps this off the syscall path for the languages a process actually uses. **Signature:** ```c int32_t ts_pack_language_registry_has_language(TS_PACKAlefHandle this, const char* name); ``` **Example:** ```c int32_t result = ts_pack_language_registry_has_language(instance, "value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------- | -------- | ----------- | | `name` | `const char*` | Yes | The name | **Returns:** `int32_t` ###### ts\_pack\_language\_registry\_language\_count() [Section titled “ts\_pack\_language\_registry\_language\_count()”](#ts_pack_language_registry_language_count) Return the total number of available languages (including aliases). Counts the same set `available_languages` lists, without materialising or sorting it. **Signature:** ```c uintptr_t ts_pack_language_registry_language_count(TS_PACKAlefHandle this); ``` **Example:** ```c uintptr_t result = ts_pack_language_registry_language_count(instance); ``` **Returns:** `uintptr_t` ###### ts\_pack\_language\_registry\_process() [Section titled “ts\_pack\_language\_registry\_process()”](#ts_pack_language_registry_process) Parse source code and extract file intelligence based on config in a single pass. **Errors:** Returns `Error.InvalidRange` if the config is invalid (see `ProcessConfig.validate`) or if the source exceeds the configured `max_source_bytes`; `Error.LanguageNotFound` if the language is unknown; or `Error.ParseFailed` if parsing produces no tree. **Signature:** ```c TS_PACKAlefHandle ts_pack_language_registry_process(TS_PACKAlefHandle this, const char* source, TS_PACKAlefHandle config); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_language_registry_process(instance, "value", 0); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------------- | -------- | ------------------------- | | `source` | `const char*` | Yes | The source | | `config` | `TS_PACKAlefHandle` | Yes | The configuration options | **Returns:** `TS_PACKAlefHandle` **Errors:** Returns the sentinel handle `0` on error. *** #### TS\_PACKNode [Section titled “TS\_PACKNode”](#ts_packnode) **C representation:** `TS_PACKNode` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKNode` does not appear anywhere in the generated header. A single syntax node within a `Tree`. Nodes hold a strong reference to their parent tree so they remain valid regardless of how the tree is moved or stored at the FFI boundary. ##### Methods [Section titled “Methods”](#methods-2) ###### ts\_pack\_node\_kind() [Section titled “ts\_pack\_node\_kind()”](#ts_pack_node_kind) Return the node’s kind name (e.g. `"function_definition"`). **Signature:** ```c const char* ts_pack_node_kind(TS_PACKAlefHandle this); ``` **Example:** ```c const char *result = ts_pack_node_kind(instance); ``` **Returns:** `const char*` ###### ts\_pack\_node\_kind\_id() [Section titled “ts\_pack\_node\_kind\_id()”](#ts_pack_node_kind_id) Return the node’s numeric kind ID. Tree-sitter assigns a stable `u16` ID to every node kind in a grammar (e.g. `"function_definition" → 42`). Comparing `kind_id()` is cheaper than comparing the string `kind()` in tight AST loops. **Signature:** ```c uint16_t ts_pack_node_kind_id(TS_PACKAlefHandle this); ``` **Example:** ```c uint16_t result = ts_pack_node_kind_id(instance); ``` **Returns:** `uint16_t` ###### ts\_pack\_node\_start\_byte() [Section titled “ts\_pack\_node\_start\_byte()”](#ts_pack_node_start_byte) Return the inclusive start byte offset of this node. **Signature:** ```c uintptr_t ts_pack_node_start_byte(TS_PACKAlefHandle this); ``` **Example:** ```c uintptr_t result = ts_pack_node_start_byte(instance); ``` **Returns:** `uintptr_t` ###### ts\_pack\_node\_end\_byte() [Section titled “ts\_pack\_node\_end\_byte()”](#ts_pack_node_end_byte) Return the exclusive end byte offset of this node. **Signature:** ```c uintptr_t ts_pack_node_end_byte(TS_PACKAlefHandle this); ``` **Example:** ```c uintptr_t result = ts_pack_node_end_byte(instance); ``` **Returns:** `uintptr_t` ###### ts\_pack\_node\_byte\_range() [Section titled “ts\_pack\_node\_byte\_range()”](#ts_pack_node_byte_range) Return the node’s byte range as a `ByteRange`. Callers should slice their own source bytes — this is a zero-copy text accessor. **Signature:** ```c TS_PACKAlefHandle ts_pack_node_byte_range(TS_PACKAlefHandle this); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_node_byte_range(instance); ``` **Returns:** `TS_PACKAlefHandle` ###### ts\_pack\_node\_start\_position() [Section titled “ts\_pack\_node\_start\_position()”](#ts_pack_node_start_position) Return the start `Point` (row, column). **Signature:** ```c TS_PACKAlefHandle ts_pack_node_start_position(TS_PACKAlefHandle this); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_node_start_position(instance); ``` **Returns:** `TS_PACKAlefHandle` ###### ts\_pack\_node\_end\_position() [Section titled “ts\_pack\_node\_end\_position()”](#ts_pack_node_end_position) Return the end `Point` (row, column). **Signature:** ```c TS_PACKAlefHandle ts_pack_node_end_position(TS_PACKAlefHandle this); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_node_end_position(instance); ``` **Returns:** `TS_PACKAlefHandle` ###### ts\_pack\_node\_is\_named() [Section titled “ts\_pack\_node\_is\_named()”](#ts_pack_node_is_named) True when this node is named (not punctuation/whitespace). **Signature:** ```c int32_t ts_pack_node_is_named(TS_PACKAlefHandle this); ``` **Example:** ```c int32_t result = ts_pack_node_is_named(instance); ``` **Returns:** `int32_t` ###### ts\_pack\_node\_is\_error() [Section titled “ts\_pack\_node\_is\_error()”](#ts_pack_node_is_error) True when this is an error node. **Signature:** ```c int32_t ts_pack_node_is_error(TS_PACKAlefHandle this); ``` **Example:** ```c int32_t result = ts_pack_node_is_error(instance); ``` **Returns:** `int32_t` ###### ts\_pack\_node\_is\_missing() [Section titled “ts\_pack\_node\_is\_missing()”](#ts_pack_node_is_missing) True when this is a missing-token node. **Signature:** ```c int32_t ts_pack_node_is_missing(TS_PACKAlefHandle this); ``` **Example:** ```c int32_t result = ts_pack_node_is_missing(instance); ``` **Returns:** `int32_t` ###### ts\_pack\_node\_is\_extra() [Section titled “ts\_pack\_node\_is\_extra()”](#ts_pack_node_is_extra) True when this is an “extra” node (e.g. a comment). **Signature:** ```c int32_t ts_pack_node_is_extra(TS_PACKAlefHandle this); ``` **Example:** ```c int32_t result = ts_pack_node_is_extra(instance); ``` **Returns:** `int32_t` ###### ts\_pack\_node\_has\_error() [Section titled “ts\_pack\_node\_has\_error()”](#ts_pack_node_has_error) True when this node or any descendant is an error. **Signature:** ```c int32_t ts_pack_node_has_error(TS_PACKAlefHandle this); ``` **Example:** ```c int32_t result = ts_pack_node_has_error(instance); ``` **Returns:** `int32_t` ###### ts\_pack\_node\_parent() [Section titled “ts\_pack\_node\_parent()”](#ts_pack_node_parent) Return this node’s parent, if any. **Signature:** ```c TS_PACKAlefHandle ts_pack_node_parent(TS_PACKAlefHandle this); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_node_parent(instance); ``` **Returns:** `TS_PACKAlefHandle` ###### ts\_pack\_node\_child() [Section titled “ts\_pack\_node\_child()”](#ts_pack_node_child) Return the i-th child of this node, if any. **Signature:** ```c TS_PACKAlefHandle ts_pack_node_child(TS_PACKAlefHandle this, uint32_t index); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_node_child(instance, 42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | ---------- | -------- | ----------- | | `index` | `uint32_t` | Yes | The index | **Returns:** `TS_PACKAlefHandle` ###### ts\_pack\_node\_child\_count() [Section titled “ts\_pack\_node\_child\_count()”](#ts_pack_node_child_count) Total number of children (including unnamed). **Signature:** ```c uintptr_t ts_pack_node_child_count(TS_PACKAlefHandle this); ``` **Example:** ```c uintptr_t result = ts_pack_node_child_count(instance); ``` **Returns:** `uintptr_t` ###### ts\_pack\_node\_named\_child() [Section titled “ts\_pack\_node\_named\_child()”](#ts_pack_node_named_child) Return the i-th named child of this node, if any. **Signature:** ```c TS_PACKAlefHandle ts_pack_node_named_child(TS_PACKAlefHandle this, uint32_t index); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_node_named_child(instance, 42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | ---------- | -------- | ----------- | | `index` | `uint32_t` | Yes | The index | **Returns:** `TS_PACKAlefHandle` ###### ts\_pack\_node\_named\_child\_count() [Section titled “ts\_pack\_node\_named\_child\_count()”](#ts_pack_node_named_child_count) Number of named children of this node. **Signature:** ```c uintptr_t ts_pack_node_named_child_count(TS_PACKAlefHandle this); ``` **Example:** ```c uintptr_t result = ts_pack_node_named_child_count(instance); ``` **Returns:** `uintptr_t` ###### ts\_pack\_node\_child\_by\_field\_name() [Section titled “ts\_pack\_node\_child\_by\_field\_name()”](#ts_pack_node_child_by_field_name) Look up a child by its grammar-defined field name. **Signature:** ```c TS_PACKAlefHandle ts_pack_node_child_by_field_name(TS_PACKAlefHandle this, const char* name); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_node_child_by_field_name(instance, "value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------- | -------- | ----------- | | `name` | `const char*` | Yes | The name | **Returns:** `TS_PACKAlefHandle` ###### ts\_pack\_node\_to\_sexp() [Section titled “ts\_pack\_node\_to\_sexp()”](#ts_pack_node_to_sexp) Return the S-expression form of this node’s subtree. **Signature:** ```c const char* ts_pack_node_to_sexp(TS_PACKAlefHandle this); ``` **Example:** ```c const char *result = ts_pack_node_to_sexp(instance); ``` **Returns:** `const char*` ###### ts\_pack\_node\_walk() [Section titled “ts\_pack\_node\_walk()”](#ts_pack_node_walk) Return a `TreeCursor` positioned at this node. **Signature:** ```c TS_PACKAlefHandle ts_pack_node_walk(TS_PACKAlefHandle this); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_node_walk(instance); ``` **Returns:** `TS_PACKAlefHandle` *** #### TS\_PACKPackConfig [Section titled “TS\_PACKPackConfig”](#ts_packpackconfig) **C representation:** `TS_PACKPackConfig` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKPackConfig` does not appear anywhere in the generated header. Configuration for the tree-sitter language pack. Controls cache directory and which languages to pre-download. Can be loaded from a TOML file, constructed programmatically, or passed as a dict/object from language bindings. | Field | Type | Default | Description | | ----------- | ------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cache_dir` | `const char*` | `NULL` | Override the BASE directory the parser cache lives under. This is a base, not the final library path: the crate appends `tree-sitter-language-pack/v{version}/libs` to it, exactly as it does to the platform default. So `cache_dir = "/tmp/my-parsers"` resolves to `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`. The suffix is not cosmetic. It keeps the whole cache tree — manifest, bundles and lock file included — inside a directory this library owns and versions. Earlier releases used this path verbatim, which put those files in the configured directory’s PARENT and let a cache built by one crate version be reused by another. Default base: the platform cache dir, e.g. `~/.cache` on Linux. | | `languages` | `const char*` | `NULL` | Languages to pre-download on init. Each entry is a language name (e.g. `"python"`, `"rust"`). | | `groups` | `const char*` | `NULL` | Language groups to pre-download. Group names come from the remote manifest, so the valid set is not fixed by this library; the published manifest currently defines only `"all"`. Call `manifest_groups` to enumerate them. An unknown name makes `init` fail. | *** #### TS\_PACKParser [Section titled “TS\_PACKParser”](#ts_packparser) **C representation:** `TS_PACKParser` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKParser` does not appear anywhere in the generated header. A tree-sitter parser configured for one language at a time. ##### Methods [Section titled “Methods”](#methods-3) ###### ts\_pack\_parser\_new() [Section titled “ts\_pack\_parser\_new()”](#ts_pack_parser_new) Construct a new parser with no language set and no parse limits. Call `Parser.set_language` before parsing. Limits are opt-in via `set_max_source_bytes` and `set_parse_timeout_ms`; both default to unbounded so that existing callers are unaffected. **Signature:** ```c TS_PACKAlefHandle ts_pack_parser_new(); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_parser_new(); ``` **Returns:** `TS_PACKAlefHandle` ###### ts\_pack\_parser\_set\_max\_source\_bytes() [Section titled “ts\_pack\_parser\_set\_max\_source\_bytes()”](#ts_pack_parser_set_max_source_bytes) Refuse to parse sources longer than `max_bytes`. `NULL` (the default) means no limit. Over-limit input makes `parse` and `parse_bytes` return `NULL` after emitting a `WARN`; input is never silently truncated. See `RECOMMENDED_MAX_SOURCE_BYTES`. **Signature:** ```c void ts_pack_parser_set_max_source_bytes(TS_PACKAlefHandle this, uintptr_t max_bytes); ``` **Example:** ```c ts_pack_parser_set_max_source_bytes(instance, 42); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | ------------ | -------- | ------------- | | `max_bytes` | `uintptr_t*` | No | The max bytes | **Returns:** No return value. ###### ts\_pack\_parser\_set\_parse\_timeout\_ms() [Section titled “ts\_pack\_parser\_set\_parse\_timeout\_ms()”](#ts_pack_parser_set_parse_timeout_ms) Cancel a parse that exceeds `timeout_ms` milliseconds of wall clock. `NULL` (the default) means no budget. Cancellation runs through tree-sitter’s parse progress callback, so it is granular to that callback’s interval rather than exact. See `RECOMMENDED_PARSE_TIMEOUT_MS`. **Signature:** ```c void ts_pack_parser_set_parse_timeout_ms(TS_PACKAlefHandle this, uint64_t timeout_ms); ``` **Example:** ```c ts_pack_parser_set_parse_timeout_ms(instance, 42); ``` **Parameters:** | Name | Type | Required | Description | | ------------ | ----------- | -------- | -------------- | | `timeout_ms` | `uint64_t*` | No | The timeout ms | **Returns:** No return value. ###### ts\_pack\_parser\_set\_language() [Section titled “ts\_pack\_parser\_set\_language()”](#ts_pack_parser_set_language) Configure the parser to use the language identified by name (e.g. `"python"`). Resolves the language through the global registry — auto-downloading if necessary, when the `download` feature is enabled. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language ABI is incompatible. **Signature:** ```c int32_t ts_pack_parser_set_language(TS_PACKAlefHandle this, const char* name); ``` **Example:** ```c ts_pack_parser_set_language(instance, "value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------- | -------- | ----------- | | `name` | `const char*` | Yes | The name | **Returns:** `int32_t` status code – `0` on success, `-1` on error. **Errors:** Returns `-1` on error. ###### ts\_pack\_parser\_parse() [Section titled “ts\_pack\_parser\_parse()”](#ts_pack_parser_parse) Parse a UTF-8 source string. Returns `NULL` if no language is set, if the parse was cancelled by the configured timeout, or if the source exceeds the configured size limit. Each non-parse outcome is logged, so an empty result is never silent. ###### Concurrency [Section titled “Concurrency”](#concurrency) Parsing runs fully in parallel across threads for almost every language — no lock is taken. The exception is the small set of grammars whose external scanner keeps mutable process-global state (currently just `properties`): parses of that language are serialized against each other through an internal per-language lock, so that concurrent threads can’t corrupt shared scanner state. Every other language is unaffected by that lock and never waits on it. **Signature:** ```c TS_PACKAlefHandle ts_pack_parser_parse(TS_PACKAlefHandle this, const char* source); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_parser_parse(instance, "value"); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------- | -------- | ----------- | | `source` | `const char*` | Yes | The source | **Returns:** `TS_PACKAlefHandle` ###### ts\_pack\_parser\_parse\_bytes() [Section titled “ts\_pack\_parser\_parse\_bytes()”](#ts_pack_parser_parse_bytes) Parse a raw byte slice. Same outcomes as `parse`, including the concurrency behaviour documented there. **Signature:** ```c TS_PACKAlefHandle ts_pack_parser_parse_bytes(TS_PACKAlefHandle this, const uint8_t* source); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_parser_parse_bytes(instance, (const uint8_t *)"data"); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ---------------- | -------- | ----------- | | `source` | `const uint8_t*` | Yes | The source | **Returns:** `TS_PACKAlefHandle` ###### ts\_pack\_parser\_reset() [Section titled “ts\_pack\_parser\_reset()”](#ts_pack_parser_reset) Reset internal state. The next call to `parse` will not be incremental. **Signature:** ```c void ts_pack_parser_reset(TS_PACKAlefHandle this); ``` **Example:** ```c ts_pack_parser_reset(instance); ``` **Returns:** No return value. *** #### TS\_PACKPoint [Section titled “TS\_PACKPoint”](#ts_packpoint) **C representation:** `TS_PACKPoint` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKPoint` does not appear anywhere in the generated header. A source position — row + column, zero-indexed. | Field | Type | Default | Description | | -------- | ----------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `row` | `uintptr_t` | — | Zero-indexed row number. | | `column` | `uintptr_t` | — | Zero-indexed column, counted in **bytes** from the start of the row. This is `tree_sitter.Point.column` verbatim, and tree-sitter defines it as a byte offset — not characters, and not UTF-16 code units. Measured on a row of the form `x = ''` where `` is a single 4-byte character (an emoji), the string node reports columns `4..10`, identical to its byte range; the character columns would be `4..7` and the UTF-16 columns `4..8`. Anything that builds LSP positions (UTF-16) or editor caret columns (characters) from this field is silently wrong on every row containing a non-ASCII byte, and must re-measure the row against the source text instead. Earlier releases documented this field as UTF-16 code units; that was never what the value contained. | *** #### TS\_PACKProcessConfig [Section titled “TS\_PACKProcessConfig”](#ts_packprocessconfig) **C representation:** `TS_PACKProcessConfig` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKProcessConfig` does not appear anywhere in the generated header. Configuration for the `process()` function. Controls which analysis features are enabled and whether chunking is performed. | Field | Type | Default | Description | | ------------------ | ------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `const char*` | `""` | Language name (required). | | `structure` | `int32_t` | `true` | Extract structural items (functions, classes, etc.). Default: true. | | `imports` | `int32_t` | `true` | Extract import statements. Default: true. | | `exports` | `int32_t` | `true` | Extract export statements. Default: true. | | `comments` | `int32_t` | `false` | Extract comments. Default: false. | | `docstrings` | `int32_t` | `false` | Extract docstrings. Default: false. | | `symbols` | `int32_t` | `false` | Extract symbol definitions. Default: false. | | `diagnostics` | `int32_t` | `false` | Include parse diagnostics. Default: false. | | `chunk_max_size` | `uintptr_t*` | `NULL` | Maximum chunk size in bytes. `NULL` disables chunking. `Some(0)` is rejected by `ProcessConfig.validate` with `Error.InvalidRange`. A zero-sized chunk limit previously produced an empty chunk list and silently discarded the whole source; use `NULL` to mean “do not chunk”. | | `data_extraction` | `int32_t` | `false` | Extract hierarchical key/value data tree from data-format files. Default: false. When `true`, `ProcessResult.data` is populated with a `DataNode` tree for supported languages: JSON, YAML, TOML, `.properties`, HCL/HOCON, INI, editorconfig, KDL, CUE, CSV, PSV, PO, nginx config, Caddy config, XML, and DTD. For languages outside this set the field is left as `NULL`. | | `max_source_bytes` | `uintptr_t*` | `NULL` | Reject source longer than this many bytes instead of parsing it. Default: `NULL` (unbounded). Tree-sitter allocates and walks proportionally to input size, so an unbounded parse of attacker-supplied input is a denial-of-service vector. The default stays unbounded for backward compatibility; services handling untrusted input should opt in, e.g. with `RECOMMENDED_MAX_SOURCE_BYTES`. Exceeding the limit fails the call with `Error.InvalidRange` — the source is never silently truncated. | | `parse_timeout_ms` | `uint64_t*` | `NULL` | Wall-clock budget for the parse step, in milliseconds. Default: `NULL` (no timeout). Enforced through tree-sitter’s parse progress callback, which the parser invokes periodically; cancellation is therefore granular to that callback interval rather than exact. A parse that exceeds the budget fails with `Error.ParseTimeout`. | *** #### TS\_PACKProcessResult [Section titled “TS\_PACKProcessResult”](#ts_packprocessresult) **C representation:** `TS_PACKProcessResult` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKProcessResult` does not appear anywhere in the generated header. Complete analysis result from processing a source file. Contains metrics, structural analysis, imports/exports, comments, docstrings, symbols, diagnostics, and optionally chunked code segments. Fields are populated based on the `ProcessConfig` flags. | Field | Type | Default | Description | | ------------- | ------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `const char*` | — | The language name used to parse the source file. | | `metrics` | `TS_PACKAlefHandle` | — | File-level metrics (line counts, byte size, error count). | | `structure` | `const char*` | `NULL` | Top-level structural items (functions, classes, etc.). | | `imports` | `const char*` | `NULL` | Import statements extracted from the source. | | `exports` | `const char*` | `NULL` | Export statements extracted from the source. | | `comments` | `const char*` | `NULL` | Comments extracted from the source. | | `docstrings` | `const char*` | `NULL` | Docstrings extracted from the source. | | `symbols` | `const char*` | `NULL` | Symbol definitions (variables, types, functions) extracted from the source. | | `diagnostics` | `const char*` | `NULL` | Parse diagnostics (syntax errors, missing nodes) from tree-sitter. | | `chunks` | `const char*` | `NULL` | Syntax-aware code chunks produced when chunking is enabled. | | `data` | `TS_PACKAlefHandle` | `NULL` | Hierarchical data tree extracted when `config.data_extraction` is `true`. Populated for supported data-format languages (JSON, YAML, TOML, properties, HCL, INI, XML, CSV, and more). `NULL` when `data_extraction` is `false` (the default) or when the language is not a recognised data format. See `DataNode` for the shape of the returned tree. | *** #### TS\_PACKSpan [Section titled “TS\_PACKSpan”](#ts_packspan) **C representation:** `TS_PACKSpan` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKSpan` does not appear anywhere in the generated header. Byte and line/column range in source code. Represents both byte offsets (for slicing) and human-readable line/column positions (for display and diagnostics). | Field | Type | Default | Description | | -------------- | ----------- | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `start_byte` | `uintptr_t` | — | Inclusive start byte offset in the source. | | `end_byte` | `uintptr_t` | — | Exclusive end byte offset in the source. | | `start_line` | `uintptr_t` | — | Zero-indexed line number of the span’s start. | | `start_column` | `uintptr_t` | — | Zero-indexed column of the span’s start, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | | `end_line` | `uintptr_t` | — | Zero-indexed line number of the span’s end. | | `end_column` | `uintptr_t` | — | Zero-indexed column of the span’s end, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | *** #### TS\_PACKStructureItem [Section titled “TS\_PACKStructureItem”](#ts_packstructureitem) **C representation:** `TS_PACKStructureItem` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKStructureItem` does not appear anywhere in the generated header. A structural item (function, class, struct, etc.) in source code. | Field | Type | Default | Description | | ------------- | ------------------- | ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `kind` | `TS_PACKAlefHandle` | `TS_PACK_FUNCTION` | The kind of structural item. | | `name` | `const char*` | `NULL` | The declared name of the item, if present. | | `visibility` | `const char*` | `NULL` | Visibility modifier (e.g., `"pub"`, `"public"`, `"private"`). | | `span` | `TS_PACKAlefHandle` | — | Source span covering the entire item declaration. | | `children` | `const char*` | `NULL` | Nested structural items (e.g., methods within a class). | | `decorators` | `const char*` | `NULL` | Decorator or attribute names applied to the item. **Reserved: not yet populated.** Always empty, for every language. Recognising a decorator requires per-language grammar knowledge (a Python `decorated_definition` wrapper, Java/C# annotations, Rust attributes each have a different shape), which no extractor here implements yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | | `doc_comment` | `const char*` | `NULL` | Documentation comment attached to the item, if any. The text of the comment (or run of comments) immediately preceding the item, with no blank line in between, when that comment is classified as a doc comment. Multiple adjacent single-line doc comments (Rust `///`) are joined with `\n` in source order. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`). `NULL` for every other language, and for a preceding comment that is not in doc-comment form (a plain `#` comment in Python, Ruby, or Elixir) — Python’s docstring convention is captured separately, as `DocstringInfo`, not through this field. | | `signature` | `const char*` | `NULL` | Full signature text of the item (e.g., function parameters and return type). The item’s own source text from its start up to the start of its body (see `StructureItem.body_span`), trimmed of trailing whitespace — for example `fn add(a: i32, b: i32) -> i32` for a Rust function whose body is `{ a + b }`. `NULL` only when that text is empty, which does not happen for any item `StructureKind` currently reports. Populated for every language and kind this library extracts structure for, since it is derived from `body_span`’s boundary rather than per-language syntax. | | `body_span` | `TS_PACKAlefHandle` | `NULL` | Source span covering only the body of the item, if distinct from the declaration. | *** #### TS\_PACKSymbolInfo [Section titled “TS\_PACKSymbolInfo”](#ts_packsymbolinfo) **C representation:** `TS_PACKSymbolInfo` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKSymbolInfo` does not appear anywhere in the generated header. A symbol (variable, function, type, etc.) extracted from source code. | Field | Type | Default | Description | | ----------------- | ------------------- | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `const char*` | — | The name of the symbol. | | `kind` | `TS_PACKAlefHandle` | `TS_PACK_VARIABLE` | The kind of symbol (variable, function, class, etc.). | | `span` | `TS_PACKAlefHandle` | — | Source span covering the symbol definition. | | `type_annotation` | `const char*` | `NULL` | Explicit type annotation, if present in the source. | | `doc` | `const char*` | `NULL` | Documentation comment immediately preceding this symbol, resolved by the same walk `StructureItem.doc_comment` uses (see `doc_comment_at`) — never hard-coded `NULL`. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`) — the languages whose comment classification recognizes a doc-kind comment. `NULL` for every other language (e.g. Python, Go, Ruby, which have no doc-kind comment classification), and also `NULL` when a symbol in a supported language simply has no doc comment immediately above it. | *** #### TS\_PACKTree [Section titled “TS\_PACKTree”](#ts_packtree) **C representation:** `TS_PACKTree` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKTree` does not appear anywhere in the generated header. A parsed syntax tree. Cheap to clone (refcount bump). ##### Methods [Section titled “Methods”](#methods-4) ###### ts\_pack\_tree\_root\_node() [Section titled “ts\_pack\_tree\_root\_node()”](#ts_pack_tree_root_node) Return the root `Node` of this tree. **Signature:** ```c TS_PACKAlefHandle ts_pack_tree_root_node(TS_PACKAlefHandle this); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_tree_root_node(instance); ``` **Returns:** `TS_PACKAlefHandle` ###### ts\_pack\_tree\_walk() [Section titled “ts\_pack\_tree\_walk()”](#ts_pack_tree_walk) Return a `TreeCursor` positioned at the root. **Signature:** ```c TS_PACKAlefHandle ts_pack_tree_walk(TS_PACKAlefHandle this); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_tree_walk(instance); ``` **Returns:** `TS_PACKAlefHandle` *** #### TS\_PACKTreeCursor [Section titled “TS\_PACKTreeCursor”](#ts_packtreecursor) **C representation:** `TS_PACKTreeCursor` is a documentation-only name for this type. The C ABI hands you a scalar `TS_PACKAlefHandle` handle – the literal string `TS_PACKTreeCursor` does not appear anywhere in the generated header. A cursor for traversing a `Tree`. ##### Methods [Section titled “Methods”](#methods-5) ###### ts\_pack\_tree\_cursor\_node() [Section titled “ts\_pack\_tree\_cursor\_node()”](#ts_pack_tree_cursor_node) Return the `Node` at the cursor’s current position. **Signature:** ```c TS_PACKAlefHandle ts_pack_tree_cursor_node(TS_PACKAlefHandle this); ``` **Example:** ```c TS_PACKAlefHandle result = ts_pack_tree_cursor_node(instance); ``` **Returns:** `TS_PACKAlefHandle` ###### ts\_pack\_tree\_cursor\_goto\_first\_child() [Section titled “ts\_pack\_tree\_cursor\_goto\_first\_child()”](#ts_pack_tree_cursor_goto_first_child) Move the cursor to the first child of the current node. Returns `true` if a child existed. **Signature:** ```c int32_t ts_pack_tree_cursor_goto_first_child(TS_PACKAlefHandle this); ``` **Example:** ```c int32_t result = ts_pack_tree_cursor_goto_first_child(instance); ``` **Returns:** `int32_t` ###### ts\_pack\_tree\_cursor\_goto\_parent() [Section titled “ts\_pack\_tree\_cursor\_goto\_parent()”](#ts_pack_tree_cursor_goto_parent) Move the cursor to the parent of the current node. Returns `true` if a parent existed. **Signature:** ```c int32_t ts_pack_tree_cursor_goto_parent(TS_PACKAlefHandle this); ``` **Example:** ```c int32_t result = ts_pack_tree_cursor_goto_parent(instance); ``` **Returns:** `int32_t` ###### ts\_pack\_tree\_cursor\_goto\_next\_sibling() [Section titled “ts\_pack\_tree\_cursor\_goto\_next\_sibling()”](#ts_pack_tree_cursor_goto_next_sibling) Move the cursor to the next sibling of the current node. Returns `true` if a sibling existed. **Signature:** ```c int32_t ts_pack_tree_cursor_goto_next_sibling(TS_PACKAlefHandle this); ``` **Example:** ```c int32_t result = ts_pack_tree_cursor_goto_next_sibling(instance); ``` **Returns:** `int32_t` ###### ts\_pack\_tree\_cursor\_field\_name() [Section titled “ts\_pack\_tree\_cursor\_field\_name()”](#ts_pack_tree_cursor_field_name) Return the field name for the current node, if any. **Signature:** ```c const char* ts_pack_tree_cursor_field_name(TS_PACKAlefHandle this); ``` **Example:** ```c const char* result = ts_pack_tree_cursor_field_name(instance); ``` **Returns:** `const char*` *** ### Enums [Section titled “Enums”](#enums) #### TS\_PACKDataNodeKind [Section titled “TS\_PACKDataNodeKind”](#ts_packdatanodekind) The kind of a data node extracted from a data-format file. Classifies each node in the hierarchical `DataNode` tree returned when `data_extraction` is enabled on `ProcessConfig`. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract) Unit variants serialize as a bare string (`"KeyValue"`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ------------------- | -------------------------------------------------------------------------------------------------------------------- | | `TS_PACK_KEY_VALUE` | A key/value pair or mapping (json/toml/properties/yaml/hcl/cue/kdl pair, or a wrapper “object”/“mapping” container). | | `TS_PACK_ELEMENT` | An XML element with a tag name in `key` and attributes in `attributes`. | | `TS_PACK_SEQUENCE` | A positional sequence item (JSON array element, YAML block sequence item, CSV/PSV row or cell). | *** #### TS\_PACKStructureKind [Section titled “TS\_PACKStructureKind”](#ts_packstructurekind) The kind of structural item found in source code. Categorizes top-level and nested declarations such as functions, classes, structs, enums, traits, and more. Use `Other` for language-specific constructs that do not fit a standard category. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-1) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ------------------- | --------------------------------------------------------------------------------------------------- | | `TS_PACK_FUNCTION` | A free-standing or associated function. | | `TS_PACK_METHOD` | A method defined inside a class, struct, trait, or impl block. | | `TS_PACK_CLASS` | A class definition. | | `TS_PACK_STRUCT` | A struct definition. | | `TS_PACK_INTERFACE` | An interface or protocol definition. | | `TS_PACK_ENUM` | An enum definition. | | `TS_PACK_MODULE` | A module or package declaration. | | `TS_PACK_TRAIT` | A trait definition. | | `TS_PACK_IMPL` | An impl block (Rust) or similar implementation block. | | `TS_PACK_NAMESPACE` | A namespace declaration. | | `TS_PACK_OTHER` | A language-specific construct that does not fit any standard category. — Fields: `0`: `const char*` | *** #### TS\_PACKCommentKind [Section titled “TS\_PACKCommentKind”](#ts_packcommentkind) The kind of a comment found in source code. Distinguishes between single-line comments, block (multi-line) comments, and documentation comments. | Value | Description | | --------------- | --------------------------------------------------------------------- | | `TS_PACK_LINE` | A single-line comment (e.g., `// ...` or `# ...`). | | `TS_PACK_BLOCK` | A block or multi-line comment using slash-star delimiters. | | `TS_PACK_DOC` | A documentation comment such as `/// ...` or slash-double-star block. | *** #### TS\_PACKDocstringFormat [Section titled “TS\_PACKDocstringFormat”](#ts_packdocstringformat) The format of a docstring extracted from source code. Identifies the docstring convention used, which varies by language (e.g., Python triple-quoted strings, JSDoc, Rustdoc `///` comments). ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-2) Unit variants serialize as a bare string (`"JSDoc"`); the `Other` variant serializes as a single-keyed object (`{"Other": "rst"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ----------------------------- | ------------------------------------------------------------------------------------------------------- | | `TS_PACK_PYTHON_TRIPLE_QUOTE` | Python triple-quoted string docstring (`"""..."""`). | | `TS_PACK_JS_DOC` | JavaScript/TypeScript JSDoc block comment (opens with two stars, closes with star-slash). | | `TS_PACK_RUSTDOC` | Rust `///` or `//!` doc comment. | | `TS_PACK_GO_DOC` | Go doc comment (a comment block immediately preceding a declaration). | | `TS_PACK_JAVA_DOC` | Java Javadoc block comment (opens with two stars, closes with star-slash). | | `TS_PACK_OTHER` | A language-specific docstring format not covered by the standard variants. — Fields: `0`: `const char*` | *** #### TS\_PACKExportKind [Section titled “TS\_PACKExportKind”](#ts_packexportkind) The kind of an export statement found in source code. Covers named exports, default exports, and re-exports from other modules. | Value | Description | | ------------------- | -------------------------------------------------------------------- | | `TS_PACK_NAMED` | A named export (e.g., `export { foo }`). | | `TS_PACK_DEFAULT` | A default export (e.g., `export default foo`). | | `TS_PACK_RE_EXPORT` | A re-export from another module (e.g., `export { foo } from 'bar'`). | *** #### TS\_PACKSymbolKind [Section titled “TS\_PACKSymbolKind”](#ts_packsymbolkind) The kind of a symbol definition found in source code. Categorizes symbol definitions such as variables, constants, functions, classes, types, interfaces, enums, and modules. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-3) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ------------------- | -------------------------------------------------------------------------------- | | `TS_PACK_VARIABLE` | A variable binding. | | `TS_PACK_CONSTANT` | A constant (immutable binding). | | `TS_PACK_FUNCTION` | A function definition. | | `TS_PACK_CLASS` | A class definition. | | `TS_PACK_TYPE` | A type alias or typedef. | | `TS_PACK_INTERFACE` | An interface definition. | | `TS_PACK_ENUM` | An enum definition. | | `TS_PACK_MODULE` | A module declaration. | | `TS_PACK_OTHER` | A symbol kind not covered by the standard variants. — Fields: `0`: `const char*` | *** #### TS\_PACKDiagnosticSeverity [Section titled “TS\_PACKDiagnosticSeverity”](#ts_packdiagnosticseverity) Severity level of a diagnostic produced during parsing. Used to classify parse errors, warnings, and informational messages found in the syntax tree. | Value | Description | | ----------------- | --------------------------------------------------------------- | | `TS_PACK_ERROR` | A parse error (e.g., an `ERROR` or `MISSING` node in the tree). | | `TS_PACK_WARNING` | A warning-level diagnostic. | | `TS_PACK_INFO` | An informational diagnostic. | *** ### Errors [Section titled “Errors”](#errors) #### TS\_PACKError [Section titled “TS\_PACKError”](#ts_packerror) Errors that can occur when using the tree-sitter language pack. Covers language lookup failures, parse errors, query errors, and I/O issues. Feature-gated variants are included when `config`, `download`, or related features are enabled. ##### Matching on `Error` [Section titled “Matching on Error”](#matching-on-error) The set of variants is not stable: new failure modes are added in minor releases, and `Io`, `Json`, and `Toml` exist only under certain feature combinations, so the variant set a downstream crate sees depends on which features it enables. Downstream `match`es must therefore carry a `_` arm; `#[non_exhaustive]` makes the compiler enforce that instead of letting a feature change silently break a build. ##### C ABI error codes [Section titled “C ABI error codes”](#c-abi-error-codes) Each variant alef can see carries an explicit `alef(error_code = N)` allocation that becomes a member of the generated `AlefFfiErrorCode` C enum. These numbers are a public ABI contract: **an allocated number is never reused after its variant is removed**, and a variant’s number never changes, because C callers compare against the value, not the name. New variants take the next free number. 0-4 are reserved by alef, so allocation starts at 100. An unannotated variant is emitted as the unknown code rather than as itself, which silently flattens the taxonomy — annotate every new variant. | Variant | Description | | ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `TS_PACK_LANGUAGE_NOT_FOUND` | The requested language name (or alias) was not found in the registry. | | `TS_PACK_DYNAMIC_LOAD` | A dynamic shared library could not be loaded at runtime. | | `TS_PACK_NULL_LANGUAGE_POINTER` | The tree-sitter language function returned a null pointer for the given language name. | | `TS_PACK_PARSER_SETUP` | The language could not be applied to the parser (e.g., ABI version mismatch). | | `TS_PACK_LOCK_POISONED` | An internal `RwLock` or `Mutex` was poisoned by a previous panic. | | `TS_PACK_CONFIG` | A configuration file or value was invalid or could not be applied. | | `TS_PACK_PARSE_FAILED` | The tree-sitter parser returned no tree for the given source input. | | `TS_PACK_PARSE_TIMEOUT` | The parse was cancelled because it exceeded its configured wall-clock budget. Raised only when a budget is configured — see `ProcessConfig.parse_timeout_ms`, which defaults to `NULL`. | | `TS_PACK_QUERY_ERROR` | A tree-sitter query could not be compiled or executed. | | `TS_PACK_INVALID_RANGE` | A byte range was invalid (e.g., end before start, or out of bounds). | | `TS_PACK_DOWNLOAD` | A parser download from GitHub releases failed. | | `TS_PACK_CHECKSUM_MISMATCH` | The downloaded file’s SHA-256 digest did not match the manifest’s expected value. | | `TS_PACK_CACHE_LOCK` | The cross-process download cache lock file could not be acquired or created. | *** # C# API Reference ## C# API Reference v1.16.1 [Section titled “C# API Reference v1.16.1”](#c-api-reference-v1161) ### Functions [Section titled “Functions”](#functions) #### DetectLanguageFromExtension() [Section titled “DetectLanguageFromExtension()”](#detectlanguagefromextension) Detect language name from a file extension (without leading dot). Returns `null` for unrecognized extensions. The match is case-insensitive. **Signature:** ```csharp public static string? DetectLanguageFromExtension(string ext) ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.DetectLanguageFromExtension("value"); ``` **Parameters:** | Name | Type | Required | Description | | ----- | -------- | -------- | ----------- | | `Ext` | `string` | Yes | The ext | **Returns:** `string?` *** #### DetectLanguageFromPath() [Section titled “DetectLanguageFromPath()”](#detectlanguagefrompath) Detect language name from a file path. Extracts the file extension and looks it up. Returns `null` if the path has no extension or the extension is not recognized. **Signature:** ```csharp public static string? DetectLanguageFromPath(string path) ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.DetectLanguageFromPath("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `Path` | `string` | Yes | Path to the file | **Returns:** `string?` *** #### DetectLanguageFromContent() [Section titled “DetectLanguageFromContent()”](#detectlanguagefromcontent) Detect language name from file content using the shebang line (`#!`). Inspects only the first line of `content`. If it begins with `#!`, the interpreter name is extracted and mapped to a language name. Handles common patterns: * `#!/usr/bin/env python3` → `"python"` * `#!/bin/bash` → `"bash"` * `#!/usr/bin/env node` → `"javascript"` The `-S` flag accepted by some `env` implementations is skipped automatically. Version suffixes (e.g. `python3.11`, `ruby3.2`) are stripped before matching. A leading UTF-8 BOM (`U+FEFF`) is skipped before the `#!` check, so a BOM-prefixed script is still detected by its shebang. Returns `null` when content does not start with `#!` (after stripping a leading BOM), the shebang is malformed, or the interpreter is not recognised. **Signature:** ```csharp public static string? DetectLanguageFromContent(string content) ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.DetectLanguageFromContent("value"); ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ---------------------- | | `Content` | `string` | Yes | The content to process | **Returns:** `string?` *** #### GetHighlightsQuery() [Section titled “GetHighlightsQuery()”](#gethighlightsquery) Get the highlights query for a language, if bundled. Returns the contents of `highlights.scm` as a static string, or `null` if no highlights query is bundled for this language. **Signature:** ```csharp public static string? GetHighlightsQuery(string language) ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.GetHighlightsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `Language` | `string` | Yes | The language | **Returns:** `string?` *** #### GetInjectionsQuery() [Section titled “GetInjectionsQuery()”](#getinjectionsquery) Get the injections query for a language, if bundled. Returns the contents of `injections.scm` as a static string, or `null` if no injections query is bundled for this language. **Signature:** ```csharp public static string? GetInjectionsQuery(string language) ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.GetInjectionsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `Language` | `string` | Yes | The language | **Returns:** `string?` *** #### GetLocalsQuery() [Section titled “GetLocalsQuery()”](#getlocalsquery) Get the locals query for a language, if bundled. Returns the contents of `locals.scm` as a static string, or `null` if no locals query is bundled for this language. **Signature:** ```csharp public static string? GetLocalsQuery(string language) ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.GetLocalsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `Language` | `string` | Yes | The language | **Returns:** `string?` *** #### GetTagsQuery() [Section titled “GetTagsQuery()”](#gettagsquery) Get the tags query for a language, if bundled. Returns the contents of `tags.scm` as a static string, or `null` if no tags query is bundled for this language. **Signature:** ```csharp public static string? GetTagsQuery(string language) ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.GetTagsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `Language` | `string` | Yes | The language | **Returns:** `string?` *** #### GetIndentsQuery() [Section titled “GetIndentsQuery()”](#getindentsquery) Get the indents query for a language, if bundled. Returns the contents of `indents.scm` (used for auto-indentation) as a static string, or `null` if no indents query is bundled for this language. **Signature:** ```csharp public static string? GetIndentsQuery(string language) ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.GetIndentsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `Language` | `string` | Yes | The language | **Returns:** `string?` *** #### GetFoldsQuery() [Section titled “GetFoldsQuery()”](#getfoldsquery) Get the folds query for a language, if bundled. Returns the contents of `folds.scm` (used for code folding) as a static string, or `null` if no folds query is bundled for this language. **Signature:** ```csharp public static string? GetFoldsQuery(string language) ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.GetFoldsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `Language` | `string` | Yes | The language | **Returns:** `string?` *** #### GetLanguage() [Section titled “GetLanguage()”](#getlanguage) Get a tree-sitter `Language` by name using the global registry. Resolves language aliases (e.g., `"shell"` maps to `"bash"`). When the `download` feature is enabled (default), automatically downloads the parser from GitHub releases if not found locally. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.Download` if auto-download fails. **Signature:** ```csharp public static Language GetLanguage(string name) ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.GetLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** `Language` **Errors:** Throws `Error`. *** #### GetParser() [Section titled “GetParser()”](#getparser) Get a `Parser` pre-configured for the given language. This is a convenience function that calls `get_language` and configures a new parser in one step. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language cannot be applied to the parser. **Signature:** ```csharp public static Parser GetParser(string name) ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.GetParser("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** `Parser` **Errors:** Throws `Error`. *** #### DetectLanguage() [Section titled “DetectLanguage()”](#detectlanguage) Detect language name from a file path or extension. This compatibility alias matches the pre-Alef Python binding API. **Signature:** ```csharp public static string? DetectLanguage(string path) ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.DetectLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `Path` | `string` | Yes | Path to the file | **Returns:** `string?` *** #### AvailableLanguages() [Section titled “AvailableLanguages()”](#availablelanguages) List all available language names (sorted, deduplicated, includes aliases). Returns names of both statically compiled and dynamically loadable languages, plus any configured aliases. **Signature:** ```csharp public static List AvailableLanguages() ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.AvailableLanguages(); ``` **Returns:** `List` *** #### HasLanguage() [Section titled “HasLanguage()”](#haslanguage) Check if a language is available by name or alias. Returns `true` if the language can be loaded (statically compiled, dynamically available, or a known alias for one of these). **Signature:** ```csharp public static bool HasLanguage(string name) ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.HasLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** `bool` *** #### LanguageCount() [Section titled “LanguageCount()”](#languagecount) Return the number of available languages. Includes statically compiled languages, dynamically loadable languages, and aliases. **Signature:** ```csharp public static ulong LanguageCount() ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.LanguageCount(); ``` **Returns:** `ulong` *** #### Process() [Section titled “Process()”](#process) Process source code and extract file intelligence using the global registry. Parses the source with tree-sitter and extracts metrics, structure, imports, exports, comments, docstrings, symbols, diagnostics, and/or chunks based on the flags set in `ProcessConfig`. **Errors:** Returns `Error.InvalidRange` if the config carries a zero-valued limit or the source exceeds `ProcessConfig.max_source_bytes`, `Error.ParseTimeout` if the parse exceeds `ProcessConfig.parse_timeout_ms`, `Error.LanguageNotFound` if the language is unknown, or `Error.ParseFailed` if parsing yields no tree. **Signature:** ```csharp public static ProcessResult Process(string source, ProcessConfig config) ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.Process("value", new ProcessConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `Source` | `string` | Yes | The source | | `Config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Throws `Error`. *** #### Init() [Section titled “Init()”](#init) Initialize the language pack with the given configuration. Applies any custom cache directory, then downloads all languages and groups specified in the config. This is the recommended entry point when you want to pre-warm the cache before use. **Errors:** Returns an error if configuration cannot be applied or if downloads fail. **Signature:** ```csharp public static void Init(PackConfig config) ``` **Example:** ```csharp TreeSitterLanguagePackConverter.Init(new PackConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `Config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Throws `Error`. *** #### Configure() [Section titled “Configure()”](#configure) Apply download configuration without downloading anything. Use this to set a custom cache directory before the first call to `get_language` or any download function. Changing the cache dir after languages have been registered has no effect on already-loaded languages. `PackConfig.cache_dir` is a BASE directory, not the final libs path: this crate appends `tree-sitter-language-pack/v{version}/libs` to it, the same suffix applied to the platform default cache directory. In the example below, files actually land under `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`, never directly in `/tmp/my-parsers/`. Call `cache_dir` to read back the resolved, fully-suffixed path. **Errors:** Returns an error if the lock cannot be acquired. **Signature:** ```csharp public static void Configure(PackConfig config) ``` **Example:** ```csharp TreeSitterLanguagePackConverter.Configure(new PackConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `Config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Throws `Error`. *** #### Download() [Section titled “Download()”](#download) Download specific languages to the local cache. Returns the number of distinct languages available after the call. Already compiled or cached languages are included in the count. Aliases are resolved before counting, so `["shell", "bash"]` names one language and returns 1. **Errors:** Returns an error if any language is not available in the manifest or if the download fails. **Signature:** ```csharp public static ulong Download(List names) ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.Download(new List()); ``` **Parameters:** | Name | Type | Required | Description | | ------- | -------------- | -------- | ----------- | | `Names` | `List` | Yes | The names | **Returns:** `ulong` **Errors:** Throws `Error`. *** #### Prefetch() [Section titled “Prefetch()”](#prefetch) Prefetch grammars: download any not already loadable from disk, then load every requested language into the process registry so a subsequent hot loop only parses. Unlike `download()`, this does not trust in-memory availability — it downloads whenever a grammar is not actually loadable from disk (fixing the case where a known-but-not-downloaded grammar is reported present), then resolves and caches every requested language. Call it once, up front, before a parallel workload. **Errors:** Returns `Error.Download` if a required grammar cannot be fetched, or `Error.LanguageNotFound` if a requested name is unknown. **Signature:** ```csharp public static void Prefetch(List languages) ``` **Example:** ```csharp TreeSitterLanguagePackConverter.Prefetch(new List()); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | -------------- | -------- | ------------- | | `Languages` | `List` | Yes | The languages | **Returns:** No return value. **Errors:** Throws `Error`. *** #### DownloadAll() [Section titled “DownloadAll()”](#downloadall) Download all available languages from the remote manifest. Downloads the platform bundle and extracts every library it contains. Languages that appear in the manifest but are absent from the bundle (e.g. grammars that failed to compile at release time) are silently skipped — they are not treated as an error. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns an error if the manifest cannot be fetched or the bundle download fails. **Signature:** ```csharp public static ulong DownloadAll() ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.DownloadAll(); ``` **Returns:** `ulong` **Errors:** Throws `Error`. *** #### DownloadGroup() [Section titled “DownloadGroup()”](#downloadgroup) Download every language in a named group. Groups are defined by the remote manifest, not by this library, and let you ensure a curated set of related grammars in one call instead of listing each name to `download()`. Already-cached languages are skipped. Call `manifest_groups` to discover the group names the manifest actually defines. The published manifest currently defines a single group, `"all"`; earlier revisions of this documentation advertised `"web"`, `"data"`, and `"systems"`, which the manifest has never contained, so every call following that example failed. Do not hardcode a group name without checking. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns `Error.Download` if the manifest cannot be fetched, if the group is unknown — the message lists the groups the manifest defines — or if any constituent language fails to download. **Signature:** ```csharp public static ulong DownloadGroup(string name) ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.DownloadGroup("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** `ulong` **Errors:** Throws `Error`. *** #### ManifestLanguages() [Section titled “ManifestLanguages()”](#manifestlanguages) Return all language names available in the remote manifest (371). Fetches (and caches) the remote manifest to discover the full list of downloadable languages. Use `downloaded_languages` to list what is already cached locally. **Errors:** Returns an error if the manifest cannot be fetched. **Signature:** ```csharp public static List ManifestLanguages() ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.ManifestLanguages(); ``` **Returns:** `List` **Errors:** Throws `Error`. *** #### ManifestGroups() [Section titled “ManifestGroups()”](#manifestgroups) Return the names of every language group the remote manifest defines, sorted. Group names are manifest data, not a compile-time constant of this library, so this is the only reliable way to learn what `download_group` and `PackConfig.groups` accept. The published manifest currently defines just `"all"`. **Errors:** Returns `Error.Download` if the manifest cannot be fetched. **Signature:** ```csharp public static List ManifestGroups() ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.ManifestGroups(); ``` **Returns:** `List` **Errors:** Throws `Error`. *** #### DownloadedLanguages() [Section titled “DownloadedLanguages()”](#downloadedlanguages) Return languages that are already downloaded and cached locally. Does not perform any network requests. Returns an empty list if the cache directory does not exist or cannot be read. **Signature:** ```csharp public static List DownloadedLanguages() ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.DownloadedLanguages(); ``` **Returns:** `List` *** #### CleanCache() [Section titled “CleanCache()”](#cleancache) Delete all cached parser shared libraries. Resets the cache registration so the next call to `get_language` or a download function will re-register the (now empty) cache directory. **Errors:** Returns an error if the cache directory cannot be removed. **Signature:** ```csharp public static void CleanCache() ``` **Example:** ```csharp TreeSitterLanguagePackConverter.CleanCache(); ``` **Returns:** No return value. **Errors:** Throws `Error`. *** #### CacheDir() [Section titled “CacheDir()”](#cachedir) Return the effective cache directory path. This is `{base}/tree-sitter-language-pack/v{version}/libs/`, where `{base}` is either the custom BASE directory set via `configure` / `init` (`PackConfig.cache_dir`) or the platform default cache directory — both are suffixed identically, so a custom `cache_dir` is never used as the final libs path. The default resolves to `~/.cache/tree-sitter-language-pack/v{version}/libs/` on a typical Unix system. **Errors:** Returns an error if no cache directory can be resolved: `version` is somehow invalid, or (with no custom `cache_dir` configured) the platform reports none and `TREE_SITTER_LANGUAGE_PACK_CACHE_DIR` is unset. This crate no longer falls back to the temporary directory for the latter case — see #101 H2. **Signature:** ```csharp public static string CacheDir() ``` **Example:** ```csharp var result = TreeSitterLanguagePackConverter.CacheDir(); ``` **Returns:** `string` **Errors:** Throws `Error`. *** ### Types [Section titled “Types”](#types) #### ByteRange [Section titled “ByteRange”](#byterange) A byte range — start (inclusive) to end (exclusive). | Field | Type | Default | Description | | ------- | ------- | ------- | ---------------------------- | | `Start` | `ulong` | — | Inclusive start byte offset. | | `End` | `ulong` | — | Exclusive end byte offset. | *** #### ChunkContext [Section titled “ChunkContext”](#chunkcontext) Metadata for a single chunk of source code. | Field | Type | Default | Description | | ---------------- | --------------------- | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Language` | `string` | — | Language name used to parse this chunk. | | `ChunkIndex` | `ulong` | — | Zero-indexed position of this chunk within the file’s chunk list. | | `TotalChunks` | `ulong` | — | Total number of chunks the file was split into. | | `NodeTypes` | `List` | `new List()` | Tree-sitter node kinds that appear at the top level of this chunk. | | `ContextPath` | `List` | `new List()` | Hierarchical path of enclosing structural items (e.g., `["MyClass", "my_method"]`). | | `SymbolsDefined` | `List` | `new List()` | Names of symbols defined within this chunk. | | `Comments` | `List` | `new List()` | Comments contained within this chunk. | | `Docstrings` | `List` | `new List()` | Docstrings contained within this chunk. Populated only for Python — the same language for which `ProcessResult.docstrings` is populated, and by the same classifier. Always empty for every other language. | | `HasErrorNodes` | `bool` | — | Whether this chunk contains any tree-sitter error nodes. | *** #### CodeChunk [Section titled “CodeChunk”](#codechunk) A chunk of source code with rich metadata. | Field | Type | Default | Description | | ----------- | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `Content` | `string` | — | The raw source text of this chunk. | | `StartByte` | `ulong` | — | Inclusive start byte offset of this chunk in the original source. | | `EndByte` | `ulong` | — | Exclusive end byte offset of this chunk in the original source. | | `StartLine` | `ulong` | — | Zero-indexed start line of this chunk. | | `EndLine` | `ulong` | — | Zero-indexed row of the last byte actually included in this chunk (inclusive — the same row a `Span.end_line` would report for a node ending on that byte). Computed the same way regardless of whether the source has a trailing newline: it is always the row of `end_byte - 1`, never a phantom row past the file’s real content. | | `Metadata` | `ChunkContext` | — | Contextual metadata about this chunk. | *** #### CommentInfo [Section titled “CommentInfo”](#commentinfo) A comment extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------- | ------------------ | ----------------------------------------------------------------- | | `Text` | `string` | — | The raw text content of the comment. | | `Kind` | `CommentKind` | `CommentKind.Line` | The kind of comment (line, block, or doc). | | `Span` | `Span` | — | Source span covering the comment. | | `AssociatedNode` | `string?` | `null` | Name of the syntax node this comment is directly associated with. | *** #### DataAttribute [Section titled “DataAttribute”](#dataattribute) An XML-style attribute attached to an `Element` node. Populated only for `DataNodeKind.Element`; always empty for `KeyValue` and `Sequence` nodes. | Field | Type | Default | Description | | ------- | -------- | ------- | --------------------------------------------------------------- | | `Name` | `string` | — | Attribute name (e.g. `"class"`, `"href"`). | | `Value` | `string` | — | Attribute value as a raw string (quotes stripped). | | `Span` | `Span` | — | Source span covering the entire `name="value"` attribute token. | *** #### DataNode [Section titled “DataNode”](#datanode) A node in the hierarchical data tree produced by data-format extraction. When `ProcessConfig.data_extraction` is `true`, `ProcessResult.data` is populated with a root `DataNode` whose `children` mirror the structure of the parsed file. The `kind` field determines which other fields are meaningful: | `kind` | `key` | `value` | `attributes` | `children` | | ---------- | ------------------------- | ------------ | ------------ | -------------- | | `KeyValue` | key / mapping key / index | leaf value | empty | nested map | | `Element` | XML tag name | text content | XML attrs | child elements | | `Sequence` | positional index (`"0"`) | leaf value | empty | sub-items | | Field | Type | Default | Description | | ------------ | --------------------- | --------------------------- | ----------------------------------------------------------------------------------------------------- | | `Kind` | `DataNodeKind` | `DataNodeKind.KeyValue` | Whether this node is a key/value pair, XML element, or sequence item. | | `Key` | `string?` | `null` | Key, attribute name, tag name, or positional index (`"0"`, `"1"`, …). `null` at the document root. | | `Value` | `string?` | `null` | Leaf scalar value, if any. `null` for containers (objects, arrays, XML elements with child elements). | | `Attributes` | `List` | `new List()` | Attributes on element-shape nodes (XML `STag` attributes). Empty for all other kinds. | | `Children` | `List` | `new List()` | Children for nested containers and XML element bodies. | | `Span` | `Span` | — | Source span covering this node in the original source file. | *** #### Diagnostic [Section titled “Diagnostic”](#diagnostic) A diagnostic (syntax error, missing node, etc.) from parsing. | Field | Type | Default | Description | | ---------- | -------------------- | -------------------------- | ---------------------------------------------- | | `Message` | `string` | — | Human-readable description of the diagnostic. | | `Severity` | `DiagnosticSeverity` | `DiagnosticSeverity.Error` | Severity of the diagnostic. | | `Span` | `Span` | — | Source span where the diagnostic was detected. | *** #### DocSection [Section titled “DocSection”](#docsection) A section within a docstring (e.g., Args, Returns, Raises). | Field | Type | Default | Description | | ------------- | --------- | ------- | ------------------------------------------------------- | | `Kind` | `string` | — | Section kind (e.g., `"args"`, `"returns"`, `"raises"`). | | `Name` | `string?` | `null` | Parameter or return value name, if applicable. | | `Description` | `string` | — | Description text for this section. | *** #### DocstringInfo [Section titled “DocstringInfo”](#docstringinfo) A docstring extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------------ | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Text` | `string` | — | The raw text of the docstring. | | `Format` | `DocstringFormat` | `DocstringFormat.PythonTripleQuote` | The docstring format (Python, JSDoc, Rustdoc, etc.). | | `Span` | `Span` | — | Source span covering the docstring. | | `AssociatedItem` | `string?` | `null` | Name of the item this docstring documents. | | `ParsedSections` | `List` | `new List()` | Parsed sections of the docstring (Args, Returns, Raises, etc.). **Reserved: not yet populated.** Always empty, for every `DocstringFormat`. Parsing a docstring body into sections requires implementing each convention’s own layout (Google/NumPy/reST style for Python, `@param`/`@returns` for JSDoc/Javadoc, and so on), which no extractor here does yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | *** #### DownloadManager [Section titled “DownloadManager”](#downloadmanager) Manages downloading and caching of pre-built parser shared libraries. ##### Methods [Section titled “Methods”](#methods) ###### New() [Section titled “New()”](#new) Create a new download manager for the given version. **Errors:** Returns `Error.Download` if `version` is empty, contains a path separator or `..`, or contains a character outside `[A-Za-z0-9.+-]` — see `validate_version` — or if no cache directory can be resolved (see `Self.default_cache_dir`). **Signature:** ```csharp public DownloadManager(string version) ``` **Example:** ```csharp var result = new DownloadManager("value"); ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ----------- | | `Version` | `string` | Yes | The version | **Returns:** `DownloadManager` **Errors:** Throws `Error`. ###### InstalledLanguages() [Section titled “InstalledLanguages()”](#installedlanguages) List languages that are already downloaded and cached. Derived from the on-disk cache filenames, one canonical name per file, plus every alias that resolves to it (via `aliases_for`) — so this list agrees with the user-facing `LanguageRegistry.available_languages` about which names are “available”; both report `"shell"` once `bash` is cached, for example. A previous version reported canonical names only, which could never agree with `available_languages()`. See #107. Returns an empty list if the cache directory does not exist. If it exists but cannot be read (e.g. a permission error), also returns an empty list — changing this to a `Result` would be a breaking change across every language binding — but logs a `tracing.warn!` so the failure is not silently indistinguishable from “nothing installed”. **Signature:** ```csharp public List InstalledLanguages() ``` **Example:** ```csharp var result = instance.InstalledLanguages(); ``` **Returns:** `List` ###### DownloadAllBestEffort() [Section titled “DownloadAllBestEffort()”](#downloadallbesteffort) Download the platform bundle and extract every library file it contains. Unlike `Self.ensure_languages`, this does not check the manifest language list against archive contents — it simply extracts all `.so`/`.dylib`/`.dll` files from the bundle. Languages in the manifest that are missing from the archive are silently ignored rather than returning an error. Returns the number of library files extracted (including those already cached). **Signature:** ```csharp public ulong DownloadAllBestEffort() ``` **Example:** ```csharp var result = instance.DownloadAllBestEffort(); ``` **Returns:** `ulong` **Errors:** Throws `Error`. ###### CleanCache() [Section titled “CleanCache()”](#cleancache-1) Remove all cached parser libraries. Acquires the cross-process lock so `clean_cache` cannot race a concurrent downloader (avoids Windows sharing-violation errors against an in-flight bundle write). The `.download.lock` file itself is **not** removed — it is permanent infrastructure; deleting it could allow a concurrent process that already opened the file to continue holding a stale lock handle while a new process opens a fresh inode, breaking the mutual-exclusion guarantee. **Signature:** ```csharp public void CleanCache() ``` **Example:** ```csharp instance.CleanCache(); ``` **Returns:** No return value. **Errors:** Throws `Error`. *** #### ExportInfo [Section titled “ExportInfo”](#exportinfo) An export statement extracted from source code. | Field | Type | Default | Description | | ------ | ------------ | ------------------ | -------------------------------------------------- | | `Name` | `string` | — | The exported name. | | `Kind` | `ExportKind` | `ExportKind.Named` | The kind of export (named, default, or re-export). | | `Span` | `Span` | — | Source span covering the export statement. | *** #### FileMetrics [Section titled “FileMetrics”](#filemetrics) Aggregate metrics for a source file. | Field | Type | Default | Description | | -------------- | ------- | ------- | -------------------------------------------------------------- | | `TotalLines` | `ulong` | — | Total number of lines (including blank and comment lines). | | `CodeLines` | `ulong` | — | Number of lines containing non-blank, non-comment source code. | | `CommentLines` | `ulong` | — | Number of lines that are entirely comments. | | `BlankLines` | `ulong` | — | Number of blank (whitespace-only) lines. | | `TotalBytes` | `ulong` | — | Total byte length of the source file. | | `NodeCount` | `ulong` | — | Total number of nodes in the syntax tree. | | `ErrorCount` | `ulong` | — | Number of error nodes in the syntax tree (parse errors). | | `MaxDepth` | `ulong` | — | Maximum nesting depth reached in the syntax tree. | *** #### ImportInfo [Section titled “ImportInfo”](#importinfo) An import statement extracted from source code. | Field | Type | Default | Description | | ------------ | -------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Source` | `string` | — | The module or path being imported from. | | `Items` | `List` | `new List()` | Specific names imported from the source module. For `import a, b` / `from m import a, b`, every entry’s base name (never the alias). For a JavaScript/TypeScript named-imports clause (`import { a, b as c } from 'm'`), every specifier’s original name. Populated for Python and JavaScript/TypeScript only. Always empty for every other language this library recognises import statements for — Rust, Go, Java, Kotlin, and Elixir (`import`/`alias`/`require`/`use`) — and for a JS/TS namespace import (`import * as ns`) or default import (`import x from 'm'`), neither of which names individual items. | | `Alias` | `string?` | `null` | Alias assigned to the import (e.g., `import numpy as np`). Populated for Python’s single-name form (`import numpy as np`, `from m import a as b`) and JavaScript/TypeScript’s namespace form (`import * as ns from 'm'`) or a named-imports clause naming exactly one specifier (`import { a as b } from 'm'`). `null` for Rust, Go, Java, Kotlin, and Elixir (which has its own `as:` alias option on `alias` directives, not yet extracted here) — and for a Python statement that aliases several names at once (`import os, sys as s`), where there is no single alias to report for the statement as a whole, so only `items` is populated for it. | | `IsWildcard` | `bool` | — | Whether this is a wildcard import (e.g., `import *` or `use foo.*`). Detected from the syntax tree — a dedicated wildcard node (`wildcard_import` in Python, `use_wildcard` in Rust) or a bare `*` token outside of string-literal content — not by searching the import’s source text for a `*` character, so a glob in an import path string (`import a from './glob*.js'`) is not mistaken for one. | | `Span` | `Span` | — | Source span covering the import statement. | *** #### Language [Section titled “Language”](#language) *** #### LanguageRegistry [Section titled “LanguageRegistry”](#languageregistry) Thread-safe registry of tree-sitter language parsers. Manages both statically compiled and dynamically loaded language grammars. Use `LanguageRegistry.new()` for the default registry, or access the global instance via the module-level convenience functions (`get_language`, `available_languages`, etc.). ##### Methods [Section titled “Methods”](#methods-1) ###### New() [Section titled “New()”](#new-1) Create a new registry populated with all statically compiled languages. When the `dynamic-loading` feature is enabled, the registry also knows about dynamically loadable grammars and will load them on demand. **Signature:** ```csharp public static LanguageRegistry New() ``` **Example:** ```csharp var result = LanguageRegistry.New(); ``` **Returns:** `LanguageRegistry` ###### GetLanguage() [Section titled “GetLanguage()”](#getlanguage-1) Get a tree-sitter `Language` by name. Resolves aliases (e.g., `"shell"` -> `"bash"`, `"makefile"` -> `"make"`), then looks up the language in the static table. When the `dynamic-loading` feature is enabled, falls back to loading a shared library on demand. **Errors:** Returns `Error.LanguageNotFound` if the name (after alias resolution) does not match any known grammar. **Signature:** ```csharp public Language GetLanguage(string name) ``` **Example:** ```csharp var result = instance.GetLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** `Language` **Errors:** Throws `Error`. ###### AvailableLanguages() [Section titled “AvailableLanguages()”](#availablelanguages-1) List all available language names, sorted and deduplicated. Includes statically compiled languages, dynamically loadable languages (if the `dynamic-loading` feature is enabled), and all configured aliases. **Signature:** ```csharp public List AvailableLanguages() ``` **Example:** ```csharp var result = instance.AvailableLanguages(); ``` **Returns:** `List` ###### HasParser() [Section titled “HasParser()”](#hasparser) Check whether this language can be parsed right now, without downloading. Resolves aliases, then answers from exactly the lookup `get_language` performs: the statically compiled table, the already-loaded dynamic grammars, and the parser shared libraries present in the primary and extra (download-cache) library directories. It never performs network I/O. A previous implementation consulted only the statically compiled table. That table is empty in every build that does not set `TSLP_LANGUAGES`, so the function answered `false` for languages this registry parses perfectly well. Contrast `has_language`, which is also `true` for a grammar that is merely *known to the manifest* and would have to be downloaded first. The pair distinguishes “we can parse it offline, now” from “we recognise the name”. The first `true` answer for a dynamic grammar loads its shared library: loading is the only way to know the grammar is usable, since a truncated or wrong-architecture library exists on disk but cannot parse. Loads are cached process-wide, so repeat calls are cheap. **Signature:** ```csharp public bool HasParser(string name) ``` **Example:** ```csharp var result = instance.HasParser("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** `bool` ###### HasLanguage() [Section titled “HasLanguage()”](#haslanguage-1) Check whether a language is available by name or alias. Returns `true` if the language can be loaded, either from the static table or from a dynamic library on disk. Every branch is one more way to answer `true`, so they are ordered cheapest-first and the filesystem is only consulted once every in-memory source has said no. Probing the loaded-grammar map and the manifest ahead of the `stat` calls is what keeps this off the syscall path for the languages a process actually uses. **Signature:** ```csharp public bool HasLanguage(string name) ``` **Example:** ```csharp var result = instance.HasLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** `bool` ###### LanguageCount() [Section titled “LanguageCount()”](#languagecount-1) Return the total number of available languages (including aliases). Counts the same set `available_languages` lists, without materialising or sorting it. **Signature:** ```csharp public ulong LanguageCount() ``` **Example:** ```csharp var result = instance.LanguageCount(); ``` **Returns:** `ulong` ###### Process() [Section titled “Process()”](#process-1) Parse source code and extract file intelligence based on config in a single pass. **Errors:** Returns `Error.InvalidRange` if the config is invalid (see `ProcessConfig.validate`) or if the source exceeds the configured `max_source_bytes`; `Error.LanguageNotFound` if the language is unknown; or `Error.ParseFailed` if parsing produces no tree. **Signature:** ```csharp public ProcessResult Process(string source, ProcessConfig config) ``` **Example:** ```csharp var result = instance.Process("value", new ProcessConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `Source` | `string` | Yes | The source | | `Config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Throws `Error`. *** #### Node [Section titled “Node”](#node) A single syntax node within a `Tree`. Nodes hold a strong reference to their parent tree so they remain valid regardless of how the tree is moved or stored at the FFI boundary. ##### Methods [Section titled “Methods”](#methods-2) ###### Kind() [Section titled “Kind()”](#kind) Return the node’s kind name (e.g. `"function_definition"`). **Signature:** ```csharp public string Kind() ``` **Example:** ```csharp var result = instance.Kind(); ``` **Returns:** `string` ###### KindId() [Section titled “KindId()”](#kindid) Return the node’s numeric kind ID. Tree-sitter assigns a stable `u16` ID to every node kind in a grammar (e.g. `"function_definition" → 42`). Comparing `kind_id()` is cheaper than comparing the string `kind()` in tight AST loops. **Signature:** ```csharp public ushort KindId() ``` **Example:** ```csharp var result = instance.KindId(); ``` **Returns:** `ushort` ###### StartByte() [Section titled “StartByte()”](#startbyte) Return the inclusive start byte offset of this node. **Signature:** ```csharp public ulong StartByte() ``` **Example:** ```csharp var result = instance.StartByte(); ``` **Returns:** `ulong` ###### EndByte() [Section titled “EndByte()”](#endbyte) Return the exclusive end byte offset of this node. **Signature:** ```csharp public ulong EndByte() ``` **Example:** ```csharp var result = instance.EndByte(); ``` **Returns:** `ulong` ###### ByteRange() [Section titled “ByteRange()”](#byterange-1) Return the node’s byte range as a `ByteRange`. Callers should slice their own source bytes — this is a zero-copy text accessor. **Signature:** ```csharp public ByteRange ByteRange() ``` **Example:** ```csharp var result = instance.ByteRange(); ``` **Returns:** `ByteRange` ###### StartPosition() [Section titled “StartPosition()”](#startposition) Return the start `Point` (row, column). **Signature:** ```csharp public Point StartPosition() ``` **Example:** ```csharp var result = instance.StartPosition(); ``` **Returns:** `Point` ###### EndPosition() [Section titled “EndPosition()”](#endposition) Return the end `Point` (row, column). **Signature:** ```csharp public Point EndPosition() ``` **Example:** ```csharp var result = instance.EndPosition(); ``` **Returns:** `Point` ###### IsNamed() [Section titled “IsNamed()”](#isnamed) True when this node is named (not punctuation/whitespace). **Signature:** ```csharp public bool IsNamed() ``` **Example:** ```csharp var result = instance.IsNamed(); ``` **Returns:** `bool` ###### IsError() [Section titled “IsError()”](#iserror) True when this is an error node. **Signature:** ```csharp public bool IsError() ``` **Example:** ```csharp var result = instance.IsError(); ``` **Returns:** `bool` ###### IsMissing() [Section titled “IsMissing()”](#ismissing) True when this is a missing-token node. **Signature:** ```csharp public bool IsMissing() ``` **Example:** ```csharp var result = instance.IsMissing(); ``` **Returns:** `bool` ###### IsExtra() [Section titled “IsExtra()”](#isextra) True when this is an “extra” node (e.g. a comment). **Signature:** ```csharp public bool IsExtra() ``` **Example:** ```csharp var result = instance.IsExtra(); ``` **Returns:** `bool` ###### HasError() [Section titled “HasError()”](#haserror) True when this node or any descendant is an error. **Signature:** ```csharp public bool HasError() ``` **Example:** ```csharp var result = instance.HasError(); ``` **Returns:** `bool` ###### Parent() [Section titled “Parent()”](#parent) Return this node’s parent, if any. **Signature:** ```csharp public Node? Parent() ``` **Example:** ```csharp var result = instance.Parent(); ``` **Returns:** `Node?` ###### Child() [Section titled “Child()”](#child) Return the i-th child of this node, if any. **Signature:** ```csharp public Node? Child(uint index) ``` **Example:** ```csharp var result = instance.Child(42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | ------ | -------- | ----------- | | `Index` | `uint` | Yes | The index | **Returns:** `Node?` ###### ChildCount() [Section titled “ChildCount()”](#childcount) Total number of children (including unnamed). **Signature:** ```csharp public ulong ChildCount() ``` **Example:** ```csharp var result = instance.ChildCount(); ``` **Returns:** `ulong` ###### NamedChild() [Section titled “NamedChild()”](#namedchild) Return the i-th named child of this node, if any. **Signature:** ```csharp public Node? NamedChild(uint index) ``` **Example:** ```csharp var result = instance.NamedChild(42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | ------ | -------- | ----------- | | `Index` | `uint` | Yes | The index | **Returns:** `Node?` ###### NamedChildCount() [Section titled “NamedChildCount()”](#namedchildcount) Number of named children of this node. **Signature:** ```csharp public ulong NamedChildCount() ``` **Example:** ```csharp var result = instance.NamedChildCount(); ``` **Returns:** `ulong` ###### ChildByFieldName() [Section titled “ChildByFieldName()”](#childbyfieldname) Look up a child by its grammar-defined field name. **Signature:** ```csharp public Node? ChildByFieldName(string name) ``` **Example:** ```csharp var result = instance.ChildByFieldName("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** `Node?` ###### ToSexp() [Section titled “ToSexp()”](#tosexp) Return the S-expression form of this node’s subtree. **Signature:** ```csharp public string ToSexp() ``` **Example:** ```csharp var result = instance.ToSexp(); ``` **Returns:** `string` ###### Walk() [Section titled “Walk()”](#walk) Return a `TreeCursor` positioned at this node. **Signature:** ```csharp public TreeCursor Walk() ``` **Example:** ```csharp var result = instance.Walk(); ``` **Returns:** `TreeCursor` *** #### PackConfig [Section titled “PackConfig”](#packconfig) Configuration for the tree-sitter language pack. Controls cache directory and which languages to pre-download. Can be loaded from a TOML file, constructed programmatically, or passed as a dict/object from language bindings. | Field | Type | Default | Description | | ----------- | --------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `CacheDir` | `string?` | `null` | Override the BASE directory the parser cache lives under. This is a base, not the final library path: the crate appends `tree-sitter-language-pack/v{version}/libs` to it, exactly as it does to the platform default. So `cache_dir = "/tmp/my-parsers"` resolves to `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`. The suffix is not cosmetic. It keeps the whole cache tree — manifest, bundles and lock file included — inside a directory this library owns and versions. Earlier releases used this path verbatim, which put those files in the configured directory’s PARENT and let a cache built by one crate version be reused by another. Default base: the platform cache dir, e.g. `~/.cache` on Linux. | | `Languages` | `List?` | `new List()` | Languages to pre-download on init. Each entry is a language name (e.g. `"python"`, `"rust"`). | | `Groups` | `List?` | `new List()` | Language groups to pre-download. Group names come from the remote manifest, so the valid set is not fixed by this library; the published manifest currently defines only `"all"`. Call `manifest_groups` to enumerate them. An unknown name makes `init` fail. | *** #### Parser [Section titled “Parser”](#parser) A tree-sitter parser configured for one language at a time. ##### Methods [Section titled “Methods”](#methods-3) ###### New() [Section titled “New()”](#new-2) Construct a new parser with no language set and no parse limits. Call `Parser.set_language` before parsing. Limits are opt-in via `set_max_source_bytes` and `set_parse_timeout_ms`; both default to unbounded so that existing callers are unaffected. **Signature:** ```csharp public static Parser New() ``` **Example:** ```csharp var result = Parser.New(); ``` **Returns:** `Parser` ###### SetMaxSourceBytes() [Section titled “SetMaxSourceBytes()”](#setmaxsourcebytes) Refuse to parse sources longer than `max_bytes`. `null` (the default) means no limit. Over-limit input makes `parse` and `parse_bytes` return `null` after emitting a `WARN`; input is never silently truncated. See `RECOMMENDED_MAX_SOURCE_BYTES`. **Signature:** ```csharp public void SetMaxSourceBytes(ulong maxBytes) ``` **Example:** ```csharp instance.SetMaxSourceBytes(42); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------- | | `MaxBytes` | `ulong?` | No | The max bytes | **Returns:** No return value. ###### SetParseTimeoutMs() [Section titled “SetParseTimeoutMs()”](#setparsetimeoutms) Cancel a parse that exceeds `timeout_ms` milliseconds of wall clock. `null` (the default) means no budget. Cancellation runs through tree-sitter’s parse progress callback, so it is granular to that callback’s interval rather than exact. See `RECOMMENDED_PARSE_TIMEOUT_MS`. **Signature:** ```csharp public void SetParseTimeoutMs(ulong timeoutMs) ``` **Example:** ```csharp instance.SetParseTimeoutMs(42); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | -------- | -------- | -------------- | | `TimeoutMs` | `ulong?` | No | The timeout ms | **Returns:** No return value. ###### SetLanguage() [Section titled “SetLanguage()”](#setlanguage) Configure the parser to use the language identified by name (e.g. `"python"`). Resolves the language through the global registry — auto-downloading if necessary, when the `download` feature is enabled. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language ABI is incompatible. **Signature:** ```csharp public void SetLanguage(string name) ``` **Example:** ```csharp instance.SetLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** No return value. **Errors:** Throws `Error`. ###### Parse() [Section titled “Parse()”](#parse) Parse a UTF-8 source string. Returns `null` if no language is set, if the parse was cancelled by the configured timeout, or if the source exceeds the configured size limit. Each non-parse outcome is logged, so an empty result is never silent. ###### Concurrency [Section titled “Concurrency”](#concurrency) Parsing runs fully in parallel across threads for almost every language — no lock is taken. The exception is the small set of grammars whose external scanner keeps mutable process-global state (currently just `properties`): parses of that language are serialized against each other through an internal per-language lock, so that concurrent threads can’t corrupt shared scanner state. Every other language is unaffected by that lock and never waits on it. **Signature:** ```csharp public Tree? Parse(string source) ``` **Example:** ```csharp var result = instance.Parse("value"); ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------- | -------- | ----------- | | `Source` | `string` | Yes | The source | **Returns:** `Tree?` ###### ParseBytes() [Section titled “ParseBytes()”](#parsebytes) Parse a raw byte slice. Same outcomes as `parse`, including the concurrency behaviour documented there. **Signature:** ```csharp public Tree? ParseBytes(byte[] source) ``` **Example:** ```csharp var result = instance.ParseBytes(System.Text.Encoding.UTF8.GetBytes("data")); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ---------- | -------- | ----------- | | `Source` | `byte\[\]` | Yes | The source | **Returns:** `Tree?` ###### Reset() [Section titled “Reset()”](#reset) Reset internal state. The next call to `parse` will not be incremental. **Signature:** ```csharp public void Reset() ``` **Example:** ```csharp instance.Reset(); ``` **Returns:** No return value. *** #### Point [Section titled “Point”](#point) A source position — row + column, zero-indexed. | Field | Type | Default | Description | | -------- | ------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `Row` | `ulong` | — | Zero-indexed row number. | | `Column` | `ulong` | — | Zero-indexed column, counted in **bytes** from the start of the row. This is `tree_sitter.Point.column` verbatim, and tree-sitter defines it as a byte offset — not characters, and not UTF-16 code units. Measured on a row of the form `x = ''` where `` is a single 4-byte character (an emoji), the string node reports columns `4..10`, identical to its byte range; the character columns would be `4..7` and the UTF-16 columns `4..8`. Anything that builds LSP positions (UTF-16) or editor caret columns (characters) from this field is silently wrong on every row containing a non-ASCII byte, and must re-measure the row against the source text instead. Earlier releases documented this field as UTF-16 code units; that was never what the value contained. | *** #### ProcessConfig [Section titled “ProcessConfig”](#processconfig) Configuration for the `process()` function. Controls which analysis features are enabled and whether chunking is performed. | Field | Type | Default | Description | | ---------------- | -------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Language` | `string` | `""` | Language name (required). | | `Structure` | `bool` | `true` | Extract structural items (functions, classes, etc.). Default: true. | | `Imports` | `bool` | `true` | Extract import statements. Default: true. | | `Exports` | `bool` | `true` | Extract export statements. Default: true. | | `Comments` | `bool` | `false` | Extract comments. Default: false. | | `Docstrings` | `bool` | `false` | Extract docstrings. Default: false. | | `Symbols` | `bool` | `false` | Extract symbol definitions. Default: false. | | `Diagnostics` | `bool` | `false` | Include parse diagnostics. Default: false. | | `ChunkMaxSize` | `ulong?` | `null` | Maximum chunk size in bytes. `null` disables chunking. `Some(0)` is rejected by `ProcessConfig.validate` with `Error.InvalidRange`. A zero-sized chunk limit previously produced an empty chunk list and silently discarded the whole source; use `null` to mean “do not chunk”. | | `DataExtraction` | `bool` | `false` | Extract hierarchical key/value data tree from data-format files. Default: false. When `true`, `ProcessResult.data` is populated with a `DataNode` tree for supported languages: JSON, YAML, TOML, `.properties`, HCL/HOCON, INI, editorconfig, KDL, CUE, CSV, PSV, PO, nginx config, Caddy config, XML, and DTD. For languages outside this set the field is left as `null`. | | `MaxSourceBytes` | `ulong?` | `null` | Reject source longer than this many bytes instead of parsing it. Default: `null` (unbounded). Tree-sitter allocates and walks proportionally to input size, so an unbounded parse of attacker-supplied input is a denial-of-service vector. The default stays unbounded for backward compatibility; services handling untrusted input should opt in, e.g. with `RECOMMENDED_MAX_SOURCE_BYTES`. Exceeding the limit fails the call with `Error.InvalidRange` — the source is never silently truncated. | | `ParseTimeoutMs` | `ulong?` | `null` | Wall-clock budget for the parse step, in milliseconds. Default: `null` (no timeout). Enforced through tree-sitter’s parse progress callback, which the parser invokes periodically; cancellation is therefore granular to that callback interval rather than exact. A parse that exceeds the budget fails with `Error.ParseTimeout`. | *** #### ProcessResult [Section titled “ProcessResult”](#processresult) Complete analysis result from processing a source file. Contains metrics, structural analysis, imports/exports, comments, docstrings, symbols, diagnostics, and optionally chunked code segments. Fields are populated based on the `ProcessConfig` flags. | Field | Type | Default | Description | | ------------- | --------------------- | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Language` | `string` | — | The language name used to parse the source file. | | `Metrics` | `FileMetrics` | — | File-level metrics (line counts, byte size, error count). | | `Structure` | `List` | `new List()` | Top-level structural items (functions, classes, etc.). | | `Imports` | `List` | `new List()` | Import statements extracted from the source. | | `Exports` | `List` | `new List()` | Export statements extracted from the source. | | `Comments` | `List` | `new List()` | Comments extracted from the source. | | `Docstrings` | `List` | `new List()` | Docstrings extracted from the source. | | `Symbols` | `List` | `new List()` | Symbol definitions (variables, types, functions) extracted from the source. | | `Diagnostics` | `List` | `new List()` | Parse diagnostics (syntax errors, missing nodes) from tree-sitter. | | `Chunks` | `List` | `new List()` | Syntax-aware code chunks produced when chunking is enabled. | | `Data` | `DataNode?` | `null` | Hierarchical data tree extracted when `config.data_extraction` is `true`. Populated for supported data-format languages (JSON, YAML, TOML, properties, HCL, INI, XML, CSV, and more). `null` when `data_extraction` is `false` (the default) or when the language is not a recognised data format. See `DataNode` for the shape of the returned tree. | *** #### Span [Section titled “Span”](#span) Byte and line/column range in source code. Represents both byte offsets (for slicing) and human-readable line/column positions (for display and diagnostics). | Field | Type | Default | Description | | ------------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `StartByte` | `ulong` | — | Inclusive start byte offset in the source. | | `EndByte` | `ulong` | — | Exclusive end byte offset in the source. | | `StartLine` | `ulong` | — | Zero-indexed line number of the span’s start. | | `StartColumn` | `ulong` | — | Zero-indexed column of the span’s start, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | | `EndLine` | `ulong` | — | Zero-indexed line number of the span’s end. | | `EndColumn` | `ulong` | — | Zero-indexed column of the span’s end, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | *** #### StructureItem [Section titled “StructureItem”](#structureitem) A structural item (function, class, struct, etc.) in source code. | Field | Type | Default | Description | | ------------ | --------------------- | --------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Kind` | `StructureKind` | `StructureKind.Function` | The kind of structural item. | | `Name` | `string?` | `null` | The declared name of the item, if present. | | `Visibility` | `string?` | `null` | Visibility modifier (e.g., `"pub"`, `"public"`, `"private"`). | | `Span` | `Span` | — | Source span covering the entire item declaration. | | `Children` | `List` | `new List()` | Nested structural items (e.g., methods within a class). | | `Decorators` | `List` | `new List()` | Decorator or attribute names applied to the item. **Reserved: not yet populated.** Always empty, for every language. Recognising a decorator requires per-language grammar knowledge (a Python `decorated_definition` wrapper, Java/C# annotations, Rust attributes each have a different shape), which no extractor here implements yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | | `DocComment` | `string?` | `null` | Documentation comment attached to the item, if any. The text of the comment (or run of comments) immediately preceding the item, with no blank line in between, when that comment is classified as a doc comment. Multiple adjacent single-line doc comments (Rust `///`) are joined with `\n` in source order. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`). `null` for every other language, and for a preceding comment that is not in doc-comment form (a plain `#` comment in Python, Ruby, or Elixir) — Python’s docstring convention is captured separately, as `DocstringInfo`, not through this field. | | `Signature` | `string?` | `null` | Full signature text of the item (e.g., function parameters and return type). The item’s own source text from its start up to the start of its body (see `StructureItem.body_span`), trimmed of trailing whitespace — for example `fn add(a: i32, b: i32) -> i32` for a Rust function whose body is `{ a + b }`. `null` only when that text is empty, which does not happen for any item `StructureKind` currently reports. Populated for every language and kind this library extracts structure for, since it is derived from `body_span`’s boundary rather than per-language syntax. | | `BodySpan` | `Span?` | `null` | Source span covering only the body of the item, if distinct from the declaration. | *** #### SymbolInfo [Section titled “SymbolInfo”](#symbolinfo) A symbol (variable, function, type, etc.) extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------ | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Name` | `string` | — | The name of the symbol. | | `Kind` | `SymbolKind` | `SymbolKind.Variable` | The kind of symbol (variable, function, class, etc.). | | `Span` | `Span` | — | Source span covering the symbol definition. | | `TypeAnnotation` | `string?` | `null` | Explicit type annotation, if present in the source. | | `Doc` | `string?` | `null` | Documentation comment immediately preceding this symbol, resolved by the same walk `StructureItem.doc_comment` uses (see `doc_comment_at`) — never hard-coded `null`. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`) — the languages whose comment classification recognizes a doc-kind comment. `null` for every other language (e.g. Python, Go, Ruby, which have no doc-kind comment classification), and also `null` when a symbol in a supported language simply has no doc comment immediately above it. | *** #### Tree [Section titled “Tree”](#tree) A parsed syntax tree. Cheap to clone (refcount bump). ##### Methods [Section titled “Methods”](#methods-4) ###### RootNode() [Section titled “RootNode()”](#rootnode) Return the root `Node` of this tree. **Signature:** ```csharp public Node RootNode() ``` **Example:** ```csharp var result = instance.RootNode(); ``` **Returns:** `Node` ###### Walk() [Section titled “Walk()”](#walk-1) Return a `TreeCursor` positioned at the root. **Signature:** ```csharp public TreeCursor Walk() ``` **Example:** ```csharp var result = instance.Walk(); ``` **Returns:** `TreeCursor` *** #### TreeCursor [Section titled “TreeCursor”](#treecursor) A cursor for traversing a `Tree`. ##### Methods [Section titled “Methods”](#methods-5) ###### Node() [Section titled “Node()”](#node-1) Return the `Node` at the cursor’s current position. **Signature:** ```csharp public Node Node() ``` **Example:** ```csharp var result = instance.Node(); ``` **Returns:** `Node` ###### GotoFirstChild() [Section titled “GotoFirstChild()”](#gotofirstchild) Move the cursor to the first child of the current node. Returns `true` if a child existed. **Signature:** ```csharp public bool GotoFirstChild() ``` **Example:** ```csharp var result = instance.GotoFirstChild(); ``` **Returns:** `bool` ###### GotoParent() [Section titled “GotoParent()”](#gotoparent) Move the cursor to the parent of the current node. Returns `true` if a parent existed. **Signature:** ```csharp public bool GotoParent() ``` **Example:** ```csharp var result = instance.GotoParent(); ``` **Returns:** `bool` ###### GotoNextSibling() [Section titled “GotoNextSibling()”](#gotonextsibling) Move the cursor to the next sibling of the current node. Returns `true` if a sibling existed. **Signature:** ```csharp public bool GotoNextSibling() ``` **Example:** ```csharp var result = instance.GotoNextSibling(); ``` **Returns:** `bool` ###### FieldName() [Section titled “FieldName()”](#fieldname) Return the field name for the current node, if any. **Signature:** ```csharp public string? FieldName() ``` **Example:** ```csharp var result = instance.FieldName(); ``` **Returns:** `string?` *** ### Enums [Section titled “Enums”](#enums) #### DataNodeKind [Section titled “DataNodeKind”](#datanodekind) The kind of a data node extracted from a data-format file. Classifies each node in the hierarchical `DataNode` tree returned when `data_extraction` is enabled on `ProcessConfig`. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract) Unit variants serialize as a bare string (`"KeyValue"`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ---------- | -------------------------------------------------------------------------------------------------------------------- | | `KeyValue` | A key/value pair or mapping (json/toml/properties/yaml/hcl/cue/kdl pair, or a wrapper “object”/“mapping” container). | | `Element` | An XML element with a tag name in `key` and attributes in `attributes`. | | `Sequence` | A positional sequence item (JSON array element, YAML block sequence item, CSV/PSV row or cell). | *** #### StructureKind [Section titled “StructureKind”](#structurekind) The kind of structural item found in source code. Categorizes top-level and nested declarations such as functions, classes, structs, enums, traits, and more. Use `Other` for language-specific constructs that do not fit a standard category. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-1) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | ---------------------------------------------------------------------------------------------- | | `Function` | A free-standing or associated function. | | `Method` | A method defined inside a class, struct, trait, or impl block. | | `Class` | A class definition. | | `Struct` | A struct definition. | | `Interface` | An interface or protocol definition. | | `Enum` | An enum definition. | | `Module` | A module or package declaration. | | `Trait` | A trait definition. | | `Impl` | An impl block (Rust) or similar implementation block. | | `Namespace` | A namespace declaration. | | `Other` | A language-specific construct that does not fit any standard category. — Fields: `0`: `string` | *** #### CommentKind [Section titled “CommentKind”](#commentkind) The kind of a comment found in source code. Distinguishes between single-line comments, block (multi-line) comments, and documentation comments. | Value | Description | | ------- | --------------------------------------------------------------------- | | `Line` | A single-line comment (e.g., `// ...` or `# ...`). | | `Block` | A block or multi-line comment using slash-star delimiters. | | `Doc` | A documentation comment such as `/// ...` or slash-double-star block. | *** #### DocstringFormat [Section titled “DocstringFormat”](#docstringformat) The format of a docstring extracted from source code. Identifies the docstring convention used, which varies by language (e.g., Python triple-quoted strings, JSDoc, Rustdoc `///` comments). ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-2) Unit variants serialize as a bare string (`"JSDoc"`); the `Other` variant serializes as a single-keyed object (`{"Other": "rst"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ------------------- | -------------------------------------------------------------------------------------------------- | | `PythonTripleQuote` | Python triple-quoted string docstring (`"""..."""`). | | `JsDoc` | JavaScript/TypeScript JSDoc block comment (opens with two stars, closes with star-slash). | | `Rustdoc` | Rust `///` or `//!` doc comment. | | `GoDoc` | Go doc comment (a comment block immediately preceding a declaration). | | `JavaDoc` | Java Javadoc block comment (opens with two stars, closes with star-slash). | | `Other` | A language-specific docstring format not covered by the standard variants. — Fields: `0`: `string` | *** #### ExportKind [Section titled “ExportKind”](#exportkind) The kind of an export statement found in source code. Covers named exports, default exports, and re-exports from other modules. | Value | Description | | ---------- | -------------------------------------------------------------------- | | `Named` | A named export (e.g., `export { foo }`). | | `Default` | A default export (e.g., `export default foo`). | | `ReExport` | A re-export from another module (e.g., `export { foo } from 'bar'`). | *** #### SymbolKind [Section titled “SymbolKind”](#symbolkind) The kind of a symbol definition found in source code. Categorizes symbol definitions such as variables, constants, functions, classes, types, interfaces, enums, and modules. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-3) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | --------------------------------------------------------------------------- | | `Variable` | A variable binding. | | `Constant` | A constant (immutable binding). | | `Function` | A function definition. | | `Class` | A class definition. | | `Type` | A type alias or typedef. | | `Interface` | An interface definition. | | `Enum` | An enum definition. | | `Module` | A module declaration. | | `Other` | A symbol kind not covered by the standard variants. — Fields: `0`: `string` | *** #### DiagnosticSeverity [Section titled “DiagnosticSeverity”](#diagnosticseverity) Severity level of a diagnostic produced during parsing. Used to classify parse errors, warnings, and informational messages found in the syntax tree. | Value | Description | | --------- | --------------------------------------------------------------- | | `Error` | A parse error (e.g., an `ERROR` or `MISSING` node in the tree). | | `Warning` | A warning-level diagnostic. | | `Info` | An informational diagnostic. | *** ### Errors [Section titled “Errors”](#errors) #### Error [Section titled “Error”](#error) Errors that can occur when using the tree-sitter language pack. Covers language lookup failures, parse errors, query errors, and I/O issues. Feature-gated variants are included when `config`, `download`, or related features are enabled. ##### Matching on `Error` [Section titled “Matching on Error”](#matching-on-error) The set of variants is not stable: new failure modes are added in minor releases, and `Io`, `Json`, and `Toml` exist only under certain feature combinations, so the variant set a downstream crate sees depends on which features it enables. Downstream `match`es must therefore carry a `_` arm; `#[non_exhaustive]` makes the compiler enforce that instead of letting a feature change silently break a build. ##### C ABI error codes [Section titled “C ABI error codes”](#c-abi-error-codes) Each variant alef can see carries an explicit `alef(error_code = N)` allocation that becomes a member of the generated `AlefFfiErrorCode` C enum. These numbers are a public ABI contract: **an allocated number is never reused after its variant is removed**, and a variant’s number never changes, because C callers compare against the value, not the name. New variants take the next free number. 0-4 are reserved by alef, so allocation starts at 100. An unannotated variant is emitted as the unknown code rather than as itself, which silently flattens the taxonomy — annotate every new variant. | Variant | Description | | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `LanguageNotFoundException` | The requested language name (or alias) was not found in the registry. | | `DynamicLoadException` | A dynamic shared library could not be loaded at runtime. | | `NullLanguagePointerException` | The tree-sitter language function returned a null pointer for the given language name. | | `ParserSetupException` | The language could not be applied to the parser (e.g., ABI version mismatch). | | `LockPoisonedException` | An internal `RwLock` or `Mutex` was poisoned by a previous panic. | | `ConfigException` | A configuration file or value was invalid or could not be applied. | | `ParseFailedException` | The tree-sitter parser returned no tree for the given source input. | | `ParseTimeoutException` | The parse was cancelled because it exceeded its configured wall-clock budget. Raised only when a budget is configured — see `ProcessConfig.parse_timeout_ms`, which defaults to `null`. | | `QueryErrorException` | A tree-sitter query could not be compiled or executed. | | `InvalidRangeException` | A byte range was invalid (e.g., end before start, or out of bounds). | | `DownloadException` | A parser download from GitHub releases failed. | | `ChecksumMismatchException` | The downloaded file’s SHA-256 digest did not match the manifest’s expected value. | | `CacheLockException` | The cross-process download cache lock file could not be acquired or created. | *** # Dart API Reference ## Dart API Reference v1.16.1 [Section titled “Dart API Reference v1.16.1”](#dart-api-reference-v1161) ### Functions [Section titled “Functions”](#functions) #### detectLanguageFromExtension() [Section titled “detectLanguageFromExtension()”](#detectlanguagefromextension) Detect language name from a file extension (without leading dot). Returns `null` for unrecognized extensions. The match is case-insensitive. **Signature:** ```dart Future detectLanguageFromExtension(String ext) ``` **Example:** ```dart final result = detectLanguageFromExtension("value"); ``` **Parameters:** | Name | Type | Required | Description | | ----- | -------- | -------- | ----------- | | `ext` | `String` | Yes | The ext | **Returns:** `String?` *** #### detectLanguageFromPath() [Section titled “detectLanguageFromPath()”](#detectlanguagefrompath) Detect language name from a file path. Extracts the file extension and looks it up. Returns `null` if the path has no extension or the extension is not recognized. **Signature:** ```dart Future detectLanguageFromPath(String path) ``` **Example:** ```dart final result = detectLanguageFromPath("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `path` | `String` | Yes | Path to the file | **Returns:** `String?` *** #### detectLanguageFromContent() [Section titled “detectLanguageFromContent()”](#detectlanguagefromcontent) Detect language name from file content using the shebang line (`#!`). Inspects only the first line of `content`. If it begins with `#!`, the interpreter name is extracted and mapped to a language name. Handles common patterns: * `#!/usr/bin/env python3` → `"python"` * `#!/bin/bash` → `"bash"` * `#!/usr/bin/env node` → `"javascript"` The `-S` flag accepted by some `env` implementations is skipped automatically. Version suffixes (e.g. `python3.11`, `ruby3.2`) are stripped before matching. A leading UTF-8 BOM (`U+FEFF`) is skipped before the `#!` check, so a BOM-prefixed script is still detected by its shebang. Returns `null` when content does not start with `#!` (after stripping a leading BOM), the shebang is malformed, or the interpreter is not recognised. **Signature:** ```dart Future detectLanguageFromContent(String content) ``` **Example:** ```dart final result = detectLanguageFromContent("value"); ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ---------------------- | | `content` | `String` | Yes | The content to process | **Returns:** `String?` *** #### getHighlightsQuery() [Section titled “getHighlightsQuery()”](#gethighlightsquery) Get the highlights query for a language, if bundled. Returns the contents of `highlights.scm` as a static string, or `null` if no highlights query is bundled for this language. **Signature:** ```dart Future getHighlightsQuery(String language) ``` **Example:** ```dart final result = getHighlightsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getInjectionsQuery() [Section titled “getInjectionsQuery()”](#getinjectionsquery) Get the injections query for a language, if bundled. Returns the contents of `injections.scm` as a static string, or `null` if no injections query is bundled for this language. **Signature:** ```dart Future getInjectionsQuery(String language) ``` **Example:** ```dart final result = getInjectionsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getLocalsQuery() [Section titled “getLocalsQuery()”](#getlocalsquery) Get the locals query for a language, if bundled. Returns the contents of `locals.scm` as a static string, or `null` if no locals query is bundled for this language. **Signature:** ```dart Future getLocalsQuery(String language) ``` **Example:** ```dart final result = getLocalsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getTagsQuery() [Section titled “getTagsQuery()”](#gettagsquery) Get the tags query for a language, if bundled. Returns the contents of `tags.scm` as a static string, or `null` if no tags query is bundled for this language. **Signature:** ```dart Future getTagsQuery(String language) ``` **Example:** ```dart final result = getTagsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getIndentsQuery() [Section titled “getIndentsQuery()”](#getindentsquery) Get the indents query for a language, if bundled. Returns the contents of `indents.scm` (used for auto-indentation) as a static string, or `null` if no indents query is bundled for this language. **Signature:** ```dart Future getIndentsQuery(String language) ``` **Example:** ```dart final result = getIndentsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getFoldsQuery() [Section titled “getFoldsQuery()”](#getfoldsquery) Get the folds query for a language, if bundled. Returns the contents of `folds.scm` (used for code folding) as a static string, or `null` if no folds query is bundled for this language. **Signature:** ```dart Future getFoldsQuery(String language) ``` **Example:** ```dart final result = getFoldsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getLanguage() [Section titled “getLanguage()”](#getlanguage) Get a tree-sitter `Language` by name using the global registry. Resolves language aliases (e.g., `"shell"` maps to `"bash"`). When the `download` feature is enabled (default), automatically downloads the parser from GitHub releases if not found locally. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.Download` if auto-download fails. **Signature:** ```dart Future getLanguage(String name) ``` **Example:** ```dart final result = getLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Language` **Errors:** Throws `Error`. *** #### getParser() [Section titled “getParser()”](#getparser) Get a `Parser` pre-configured for the given language. This is a convenience function that calls `get_language` and configures a new parser in one step. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language cannot be applied to the parser. **Signature:** ```dart Future getParser(String name) ``` **Example:** ```dart final result = getParser("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Parser` **Errors:** Throws `Error`. *** #### detectLanguage() [Section titled “detectLanguage()”](#detectlanguage) Detect language name from a file path or extension. This compatibility alias matches the pre-Alef Python binding API. **Signature:** ```dart Future detectLanguage(String path) ``` **Example:** ```dart final result = detectLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `path` | `String` | Yes | Path to the file | **Returns:** `String?` *** #### availableLanguages() [Section titled “availableLanguages()”](#availablelanguages) List all available language names (sorted, deduplicated, includes aliases). Returns names of both statically compiled and dynamically loadable languages, plus any configured aliases. **Signature:** ```dart Future> availableLanguages() ``` **Example:** ```dart final result = availableLanguages(); ``` **Returns:** `List` *** #### hasLanguage() [Section titled “hasLanguage()”](#haslanguage) Check if a language is available by name or alias. Returns `true` if the language can be loaded (statically compiled, dynamically available, or a known alias for one of these). **Signature:** ```dart Future hasLanguage(String name) ``` **Example:** ```dart final result = hasLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `bool` *** #### languageCount() [Section titled “languageCount()”](#languagecount) Return the number of available languages. Includes statically compiled languages, dynamically loadable languages, and aliases. **Signature:** ```dart Future languageCount() ``` **Example:** ```dart final result = languageCount(); ``` **Returns:** `PlatformInt64` *** #### process() [Section titled “process()”](#process) Process source code and extract file intelligence using the global registry. Parses the source with tree-sitter and extracts metrics, structure, imports, exports, comments, docstrings, symbols, diagnostics, and/or chunks based on the flags set in `ProcessConfig`. **Errors:** Returns `Error.InvalidRange` if the config carries a zero-valued limit or the source exceeds `ProcessConfig.max_source_bytes`, `Error.ParseTimeout` if the parse exceeds `ProcessConfig.parse_timeout_ms`, `Error.LanguageNotFound` if the language is unknown, or `Error.ParseFailed` if parsing yields no tree. **Signature:** ```dart Future process(String source, ProcessConfig config) ``` **Example:** ```dart final result = process("value", ProcessConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `String` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Throws `Error`. *** #### init() [Section titled “init()”](#init) Initialize the language pack with the given configuration. Applies any custom cache directory, then downloads all languages and groups specified in the config. This is the recommended entry point when you want to pre-warm the cache before use. **Errors:** Returns an error if configuration cannot be applied or if downloads fail. **Signature:** ```dart Future init(PackConfig config) ``` **Example:** ```dart init(PackConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Throws `Error`. *** #### configure() [Section titled “configure()”](#configure) Apply download configuration without downloading anything. Use this to set a custom cache directory before the first call to `get_language` or any download function. Changing the cache dir after languages have been registered has no effect on already-loaded languages. `PackConfig.cache_dir` is a BASE directory, not the final libs path: this crate appends `tree-sitter-language-pack/v{version}/libs` to it, the same suffix applied to the platform default cache directory. In the example below, files actually land under `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`, never directly in `/tmp/my-parsers/`. Call `cache_dir` to read back the resolved, fully-suffixed path. **Errors:** Returns an error if the lock cannot be acquired. **Signature:** ```dart Future configure(PackConfig config) ``` **Example:** ```dart configure(PackConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Throws `Error`. *** #### download() [Section titled “download()”](#download) Download specific languages to the local cache. Returns the number of distinct languages available after the call. Already compiled or cached languages are included in the count. Aliases are resolved before counting, so `["shell", "bash"]` names one language and returns 1. **Errors:** Returns an error if any language is not available in the manifest or if the download fails. **Signature:** ```dart Future download(List names) ``` **Example:** ```dart final result = download([]); ``` **Parameters:** | Name | Type | Required | Description | | ------- | -------------- | -------- | ----------- | | `names` | `List` | Yes | The names | **Returns:** `PlatformInt64` **Errors:** Throws `Error`. *** #### prefetch() [Section titled “prefetch()”](#prefetch) Prefetch grammars: download any not already loadable from disk, then load every requested language into the process registry so a subsequent hot loop only parses. Unlike `download()`, this does not trust in-memory availability — it downloads whenever a grammar is not actually loadable from disk (fixing the case where a known-but-not-downloaded grammar is reported present), then resolves and caches every requested language. Call it once, up front, before a parallel workload. **Errors:** Returns `Error.Download` if a required grammar cannot be fetched, or `Error.LanguageNotFound` if a requested name is unknown. **Signature:** ```dart Future prefetch(List languages) ``` **Example:** ```dart prefetch([]); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | -------------- | -------- | ------------- | | `languages` | `List` | Yes | The languages | **Returns:** No return value. **Errors:** Throws `Error`. *** #### downloadAll() [Section titled “downloadAll()”](#downloadall) Download all available languages from the remote manifest. Downloads the platform bundle and extracts every library it contains. Languages that appear in the manifest but are absent from the bundle (e.g. grammars that failed to compile at release time) are silently skipped — they are not treated as an error. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns an error if the manifest cannot be fetched or the bundle download fails. **Signature:** ```dart Future downloadAll() ``` **Example:** ```dart final result = downloadAll(); ``` **Returns:** `PlatformInt64` **Errors:** Throws `Error`. *** #### downloadGroup() [Section titled “downloadGroup()”](#downloadgroup) Download every language in a named group. Groups are defined by the remote manifest, not by this library, and let you ensure a curated set of related grammars in one call instead of listing each name to `download()`. Already-cached languages are skipped. Call `manifest_groups` to discover the group names the manifest actually defines. The published manifest currently defines a single group, `"all"`; earlier revisions of this documentation advertised `"web"`, `"data"`, and `"systems"`, which the manifest has never contained, so every call following that example failed. Do not hardcode a group name without checking. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns `Error.Download` if the manifest cannot be fetched, if the group is unknown — the message lists the groups the manifest defines — or if any constituent language fails to download. **Signature:** ```dart Future downloadGroup(String name) ``` **Example:** ```dart final result = downloadGroup("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `PlatformInt64` **Errors:** Throws `Error`. *** #### manifestLanguages() [Section titled “manifestLanguages()”](#manifestlanguages) Return all language names available in the remote manifest (371). Fetches (and caches) the remote manifest to discover the full list of downloadable languages. Use `downloaded_languages` to list what is already cached locally. **Errors:** Returns an error if the manifest cannot be fetched. **Signature:** ```dart Future> manifestLanguages() ``` **Example:** ```dart final result = manifestLanguages(); ``` **Returns:** `List` **Errors:** Throws `Error`. *** #### manifestGroups() [Section titled “manifestGroups()”](#manifestgroups) Return the names of every language group the remote manifest defines, sorted. Group names are manifest data, not a compile-time constant of this library, so this is the only reliable way to learn what `download_group` and `PackConfig.groups` accept. The published manifest currently defines just `"all"`. **Errors:** Returns `Error.Download` if the manifest cannot be fetched. **Signature:** ```dart Future> manifestGroups() ``` **Example:** ```dart final result = manifestGroups(); ``` **Returns:** `List` **Errors:** Throws `Error`. *** #### downloadedLanguages() [Section titled “downloadedLanguages()”](#downloadedlanguages) Return languages that are already downloaded and cached locally. Does not perform any network requests. Returns an empty list if the cache directory does not exist or cannot be read. **Signature:** ```dart Future> downloadedLanguages() ``` **Example:** ```dart final result = downloadedLanguages(); ``` **Returns:** `List` *** #### cleanCache() [Section titled “cleanCache()”](#cleancache) Delete all cached parser shared libraries. Resets the cache registration so the next call to `get_language` or a download function will re-register the (now empty) cache directory. **Errors:** Returns an error if the cache directory cannot be removed. **Signature:** ```dart Future cleanCache() ``` **Example:** ```dart cleanCache(); ``` **Returns:** No return value. **Errors:** Throws `Error`. *** #### cacheDir() [Section titled “cacheDir()”](#cachedir) Return the effective cache directory path. This is `{base}/tree-sitter-language-pack/v{version}/libs/`, where `{base}` is either the custom BASE directory set via `configure` / `init` (`PackConfig.cache_dir`) or the platform default cache directory — both are suffixed identically, so a custom `cache_dir` is never used as the final libs path. The default resolves to `~/.cache/tree-sitter-language-pack/v{version}/libs/` on a typical Unix system. **Errors:** Returns an error if no cache directory can be resolved: `version` is somehow invalid, or (with no custom `cache_dir` configured) the platform reports none and `TREE_SITTER_LANGUAGE_PACK_CACHE_DIR` is unset. This crate no longer falls back to the temporary directory for the latter case — see #101 H2. **Signature:** ```dart Future cacheDir() ``` **Example:** ```dart final result = cacheDir(); ``` **Returns:** `String` **Errors:** Throws `Error`. *** ### Types [Section titled “Types”](#types) #### ByteRange [Section titled “ByteRange”](#byterange) A byte range — start (inclusive) to end (exclusive). | Field | Type | Default | Description | | ------- | --------------- | ------- | ---------------------------- | | `start` | `PlatformInt64` | — | Inclusive start byte offset. | | `end` | `PlatformInt64` | — | Exclusive end byte offset. | *** #### ChunkContext [Section titled “ChunkContext”](#chunkcontext) Metadata for a single chunk of source code. | Field | Type | Default | Description | | ---------------- | --------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String` | — | Language name used to parse this chunk. | | `chunkIndex` | `PlatformInt64` | — | Zero-indexed position of this chunk within the file’s chunk list. | | `totalChunks` | `PlatformInt64` | — | Total number of chunks the file was split into. | | `nodeTypes` | `List` | `[]` | Tree-sitter node kinds that appear at the top level of this chunk. | | `contextPath` | `List` | `[]` | Hierarchical path of enclosing structural items (e.g., `["MyClass", "my_method"]`). | | `symbolsDefined` | `List` | `[]` | Names of symbols defined within this chunk. | | `comments` | `List` | `[]` | Comments contained within this chunk. | | `docstrings` | `List` | `[]` | Docstrings contained within this chunk. Populated only for Python — the same language for which `ProcessResult.docstrings` is populated, and by the same classifier. Always empty for every other language. | | `hasErrorNodes` | `bool` | — | Whether this chunk contains any tree-sitter error nodes. | *** #### CodeChunk [Section titled “CodeChunk”](#codechunk) A chunk of source code with rich metadata. | Field | Type | Default | Description | | ----------- | --------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `content` | `String` | — | The raw source text of this chunk. | | `startByte` | `PlatformInt64` | — | Inclusive start byte offset of this chunk in the original source. | | `endByte` | `PlatformInt64` | — | Exclusive end byte offset of this chunk in the original source. | | `startLine` | `PlatformInt64` | — | Zero-indexed start line of this chunk. | | `endLine` | `PlatformInt64` | — | Zero-indexed row of the last byte actually included in this chunk (inclusive — the same row a `Span.end_line` would report for a node ending on that byte). Computed the same way regardless of whether the source has a trailing newline: it is always the row of `end_byte - 1`, never a phantom row past the file’s real content. | | `metadata` | `ChunkContext` | — | Contextual metadata about this chunk. | *** #### CommentInfo [Section titled “CommentInfo”](#commentinfo) A comment extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------- | ------------------ | ----------------------------------------------------------------- | | `text` | `String` | — | The raw text content of the comment. | | `kind` | `CommentKind` | `CommentKind.line` | The kind of comment (line, block, or doc). | | `span` | `Span` | — | Source span covering the comment. | | `associatedNode` | `String?` | `null` | Name of the syntax node this comment is directly associated with. | *** #### DataAttribute [Section titled “DataAttribute”](#dataattribute) An XML-style attribute attached to an `Element` node. Populated only for `DataNodeKind.Element`; always empty for `KeyValue` and `Sequence` nodes. | Field | Type | Default | Description | | ------- | -------- | ------- | --------------------------------------------------------------- | | `name` | `String` | — | Attribute name (e.g. `"class"`, `"href"`). | | `value` | `String` | — | Attribute value as a raw string (quotes stripped). | | `span` | `Span` | — | Source span covering the entire `name="value"` attribute token. | *** #### DataNode [Section titled “DataNode”](#datanode) A node in the hierarchical data tree produced by data-format extraction. When `ProcessConfig.data_extraction` is `true`, `ProcessResult.data` is populated with a root `DataNode` whose `children` mirror the structure of the parsed file. The `kind` field determines which other fields are meaningful: | `kind` | `key` | `value` | `attributes` | `children` | | ---------- | ------------------------- | ------------ | ------------ | -------------- | | `KeyValue` | key / mapping key / index | leaf value | empty | nested map | | `Element` | XML tag name | text content | XML attrs | child elements | | `Sequence` | positional index (`"0"`) | leaf value | empty | sub-items | | Field | Type | Default | Description | | ------------ | --------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------- | | `kind` | `DataNodeKind` | `DataNodeKind.keyValue` | Whether this node is a key/value pair, XML element, or sequence item. | | `key` | `String?` | `null` | Key, attribute name, tag name, or positional index (`"0"`, `"1"`, …). `null` at the document root. | | `value` | `String?` | `null` | Leaf scalar value, if any. `null` for containers (objects, arrays, XML elements with child elements). | | `attributes` | `List` | `[]` | Attributes on element-shape nodes (XML `STag` attributes). Empty for all other kinds. | | `children` | `List` | `[]` | Children for nested containers and XML element bodies. | | `span` | `Span` | — | Source span covering this node in the original source file. | *** #### Diagnostic [Section titled “Diagnostic”](#diagnostic) A diagnostic (syntax error, missing node, etc.) from parsing. | Field | Type | Default | Description | | ---------- | -------------------- | -------------------------- | ---------------------------------------------- | | `message` | `String` | — | Human-readable description of the diagnostic. | | `severity` | `DiagnosticSeverity` | `DiagnosticSeverity.error` | Severity of the diagnostic. | | `span` | `Span` | — | Source span where the diagnostic was detected. | *** #### DocSection [Section titled “DocSection”](#docsection) A section within a docstring (e.g., Args, Returns, Raises). | Field | Type | Default | Description | | ------------- | --------- | ------- | ------------------------------------------------------- | | `kind` | `String` | — | Section kind (e.g., `"args"`, `"returns"`, `"raises"`). | | `name` | `String?` | `null` | Parameter or return value name, if applicable. | | `description` | `String` | — | Description text for this section. | *** #### DocstringInfo [Section titled “DocstringInfo”](#docstringinfo) A docstring extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------------ | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | `String` | — | The raw text of the docstring. | | `format` | `DocstringFormat` | `DocstringFormat.pythonTripleQuote` | The docstring format (Python, JSDoc, Rustdoc, etc.). | | `span` | `Span` | — | Source span covering the docstring. | | `associatedItem` | `String?` | `null` | Name of the item this docstring documents. | | `parsedSections` | `List` | `[]` | Parsed sections of the docstring (Args, Returns, Raises, etc.). **Reserved: not yet populated.** Always empty, for every `DocstringFormat`. Parsing a docstring body into sections requires implementing each convention’s own layout (Google/NumPy/reST style for Python, `@param`/`@returns` for JSDoc/Javadoc, and so on), which no extractor here does yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | *** #### DownloadManager [Section titled “DownloadManager”](#downloadmanager) Manages downloading and caching of pre-built parser shared libraries. ##### Methods [Section titled “Methods”](#methods) ###### create() [Section titled “create()”](#create) Create a new download manager for the given version. **Errors:** Returns `Error.Download` if `version` is empty, contains a path separator or `..`, or contains a character outside `[A-Za-z0-9.+-]` — see `validate_version` — or if no cache directory can be resolved (see `Self.default_cache_dir`). **Signature:** ```dart static Future create(String version) ``` **Example:** ```dart final result = DownloadManager.create("value"); ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ----------- | | `version` | `String` | Yes | The version | **Returns:** `DownloadManager` **Errors:** Throws `Error`. ###### installedLanguages() [Section titled “installedLanguages()”](#installedlanguages) List languages that are already downloaded and cached. Derived from the on-disk cache filenames, one canonical name per file, plus every alias that resolves to it (via `aliases_for`) — so this list agrees with the user-facing `LanguageRegistry.available_languages` about which names are “available”; both report `"shell"` once `bash` is cached, for example. A previous version reported canonical names only, which could never agree with `available_languages()`. See #107. Returns an empty list if the cache directory does not exist. If it exists but cannot be read (e.g. a permission error), also returns an empty list — changing this to a `Result` would be a breaking change across every language binding — but logs a `tracing.warn!` so the failure is not silently indistinguishable from “nothing installed”. **Signature:** ```dart Future> installedLanguages() ``` **Example:** ```dart final result = instance.installedLanguages(); ``` **Returns:** `List` ###### downloadAllBestEffort() [Section titled “downloadAllBestEffort()”](#downloadallbesteffort) Download the platform bundle and extract every library file it contains. Unlike `Self.ensure_languages`, this does not check the manifest language list against archive contents — it simply extracts all `.so`/`.dylib`/`.dll` files from the bundle. Languages in the manifest that are missing from the archive are silently ignored rather than returning an error. Returns the number of library files extracted (including those already cached). **Signature:** ```dart Future downloadAllBestEffort() ``` **Example:** ```dart final result = instance.downloadAllBestEffort(); ``` **Returns:** `PlatformInt64` **Errors:** Throws `Error`. ###### cleanCache() [Section titled “cleanCache()”](#cleancache-1) Remove all cached parser libraries. Acquires the cross-process lock so `clean_cache` cannot race a concurrent downloader (avoids Windows sharing-violation errors against an in-flight bundle write). The `.download.lock` file itself is **not** removed — it is permanent infrastructure; deleting it could allow a concurrent process that already opened the file to continue holding a stale lock handle while a new process opens a fresh inode, breaking the mutual-exclusion guarantee. **Signature:** ```dart Future cleanCache() ``` **Example:** ```dart instance.cleanCache(); ``` **Returns:** No return value. **Errors:** Throws `Error`. *** #### ExportInfo [Section titled “ExportInfo”](#exportinfo) An export statement extracted from source code. | Field | Type | Default | Description | | ------ | ------------ | ------------------ | -------------------------------------------------- | | `name` | `String` | — | The exported name. | | `kind` | `ExportKind` | `ExportKind.named` | The kind of export (named, default, or re-export). | | `span` | `Span` | — | Source span covering the export statement. | *** #### FileMetrics [Section titled “FileMetrics”](#filemetrics) Aggregate metrics for a source file. | Field | Type | Default | Description | | -------------- | --------------- | ------- | -------------------------------------------------------------- | | `totalLines` | `PlatformInt64` | — | Total number of lines (including blank and comment lines). | | `codeLines` | `PlatformInt64` | — | Number of lines containing non-blank, non-comment source code. | | `commentLines` | `PlatformInt64` | — | Number of lines that are entirely comments. | | `blankLines` | `PlatformInt64` | — | Number of blank (whitespace-only) lines. | | `totalBytes` | `PlatformInt64` | — | Total byte length of the source file. | | `nodeCount` | `PlatformInt64` | — | Total number of nodes in the syntax tree. | | `errorCount` | `PlatformInt64` | — | Number of error nodes in the syntax tree (parse errors). | | `maxDepth` | `PlatformInt64` | — | Maximum nesting depth reached in the syntax tree. | *** #### ImportInfo [Section titled “ImportInfo”](#importinfo) An import statement extracted from source code. | Field | Type | Default | Description | | ------------ | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `source` | `String` | — | The module or path being imported from. | | `items` | `List` | `[]` | Specific names imported from the source module. For `import a, b` / `from m import a, b`, every entry’s base name (never the alias). For a JavaScript/TypeScript named-imports clause (`import { a, b as c } from 'm'`), every specifier’s original name. Populated for Python and JavaScript/TypeScript only. Always empty for every other language this library recognises import statements for — Rust, Go, Java, Kotlin, and Elixir (`import`/`alias`/`require`/`use`) — and for a JS/TS namespace import (`import * as ns`) or default import (`import x from 'm'`), neither of which names individual items. | | `alias` | `String?` | `null` | Alias assigned to the import (e.g., `import numpy as np`). Populated for Python’s single-name form (`import numpy as np`, `from m import a as b`) and JavaScript/TypeScript’s namespace form (`import * as ns from 'm'`) or a named-imports clause naming exactly one specifier (`import { a as b } from 'm'`). `null` for Rust, Go, Java, Kotlin, and Elixir (which has its own `as:` alias option on `alias` directives, not yet extracted here) — and for a Python statement that aliases several names at once (`import os, sys as s`), where there is no single alias to report for the statement as a whole, so only `items` is populated for it. | | `isWildcard` | `bool` | — | Whether this is a wildcard import (e.g., `import *` or `use foo.*`). Detected from the syntax tree — a dedicated wildcard node (`wildcard_import` in Python, `use_wildcard` in Rust) or a bare `*` token outside of string-literal content — not by searching the import’s source text for a `*` character, so a glob in an import path string (`import a from './glob*.js'`) is not mistaken for one. | | `span` | `Span` | — | Source span covering the import statement. | *** #### Language [Section titled “Language”](#language) *** #### LanguageRegistry [Section titled “LanguageRegistry”](#languageregistry) Thread-safe registry of tree-sitter language parsers. Manages both statically compiled and dynamically loaded language grammars. Use `LanguageRegistry.new()` for the default registry, or access the global instance via the module-level convenience functions (`get_language`, `available_languages`, etc.). ##### Methods [Section titled “Methods”](#methods-1) ###### create() [Section titled “create()”](#create-1) Create a new registry populated with all statically compiled languages. When the `dynamic-loading` feature is enabled, the registry also knows about dynamically loadable grammars and will load them on demand. **Signature:** ```dart static Future create() ``` **Example:** ```dart final result = LanguageRegistry.create(); ``` **Returns:** `LanguageRegistry` ###### getLanguage() [Section titled “getLanguage()”](#getlanguage-1) Get a tree-sitter `Language` by name. Resolves aliases (e.g., `"shell"` -> `"bash"`, `"makefile"` -> `"make"`), then looks up the language in the static table. When the `dynamic-loading` feature is enabled, falls back to loading a shared library on demand. **Errors:** Returns `Error.LanguageNotFound` if the name (after alias resolution) does not match any known grammar. **Signature:** ```dart Future getLanguage(String name) ``` **Example:** ```dart final result = instance.getLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Language` **Errors:** Throws `Error`. ###### availableLanguages() [Section titled “availableLanguages()”](#availablelanguages-1) List all available language names, sorted and deduplicated. Includes statically compiled languages, dynamically loadable languages (if the `dynamic-loading` feature is enabled), and all configured aliases. **Signature:** ```dart Future> availableLanguages() ``` **Example:** ```dart final result = instance.availableLanguages(); ``` **Returns:** `List` ###### hasParser() [Section titled “hasParser()”](#hasparser) Check whether this language can be parsed right now, without downloading. Resolves aliases, then answers from exactly the lookup `get_language` performs: the statically compiled table, the already-loaded dynamic grammars, and the parser shared libraries present in the primary and extra (download-cache) library directories. It never performs network I/O. A previous implementation consulted only the statically compiled table. That table is empty in every build that does not set `TSLP_LANGUAGES`, so the function answered `false` for languages this registry parses perfectly well. Contrast `has_language`, which is also `true` for a grammar that is merely *known to the manifest* and would have to be downloaded first. The pair distinguishes “we can parse it offline, now” from “we recognise the name”. The first `true` answer for a dynamic grammar loads its shared library: loading is the only way to know the grammar is usable, since a truncated or wrong-architecture library exists on disk but cannot parse. Loads are cached process-wide, so repeat calls are cheap. **Signature:** ```dart Future hasParser(String name) ``` **Example:** ```dart final result = instance.hasParser("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `bool` ###### hasLanguage() [Section titled “hasLanguage()”](#haslanguage-1) Check whether a language is available by name or alias. Returns `true` if the language can be loaded, either from the static table or from a dynamic library on disk. Every branch is one more way to answer `true`, so they are ordered cheapest-first and the filesystem is only consulted once every in-memory source has said no. Probing the loaded-grammar map and the manifest ahead of the `stat` calls is what keeps this off the syscall path for the languages a process actually uses. **Signature:** ```dart Future hasLanguage(String name) ``` **Example:** ```dart final result = instance.hasLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `bool` ###### languageCount() [Section titled “languageCount()”](#languagecount-1) Return the total number of available languages (including aliases). Counts the same set `available_languages` lists, without materialising or sorting it. **Signature:** ```dart Future languageCount() ``` **Example:** ```dart final result = instance.languageCount(); ``` **Returns:** `PlatformInt64` ###### process() [Section titled “process()”](#process-1) Parse source code and extract file intelligence based on config in a single pass. **Errors:** Returns `Error.InvalidRange` if the config is invalid (see `ProcessConfig.validate`) or if the source exceeds the configured `max_source_bytes`; `Error.LanguageNotFound` if the language is unknown; or `Error.ParseFailed` if parsing produces no tree. **Signature:** ```dart Future process(String source, ProcessConfig config) ``` **Example:** ```dart final result = instance.process("value", ProcessConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `String` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Throws `Error`. *** #### Node [Section titled “Node”](#node) A single syntax node within a `Tree`. Nodes hold a strong reference to their parent tree so they remain valid regardless of how the tree is moved or stored at the FFI boundary. ##### Methods [Section titled “Methods”](#methods-2) ###### kind() [Section titled “kind()”](#kind) Return the node’s kind name (e.g. `"function_definition"`). **Signature:** ```dart Future kind() ``` **Example:** ```dart final result = instance.kind(); ``` **Returns:** `String` ###### kindId() [Section titled “kindId()”](#kindid) Return the node’s numeric kind ID. Tree-sitter assigns a stable `u16` ID to every node kind in a grammar (e.g. `"function_definition" → 42`). Comparing `kind_id()` is cheaper than comparing the string `kind()` in tight AST loops. **Signature:** ```dart Future kindId() ``` **Example:** ```dart final result = instance.kindId(); ``` **Returns:** `int` ###### startByte() [Section titled “startByte()”](#startbyte) Return the inclusive start byte offset of this node. **Signature:** ```dart Future startByte() ``` **Example:** ```dart final result = instance.startByte(); ``` **Returns:** `PlatformInt64` ###### endByte() [Section titled “endByte()”](#endbyte) Return the exclusive end byte offset of this node. **Signature:** ```dart Future endByte() ``` **Example:** ```dart final result = instance.endByte(); ``` **Returns:** `PlatformInt64` ###### byteRange() [Section titled “byteRange()”](#byterange-1) Return the node’s byte range as a `ByteRange`. Callers should slice their own source bytes — this is a zero-copy text accessor. **Signature:** ```dart Future byteRange() ``` **Example:** ```dart final result = instance.byteRange(); ``` **Returns:** `ByteRange` ###### startPosition() [Section titled “startPosition()”](#startposition) Return the start `Point` (row, column). **Signature:** ```dart Future startPosition() ``` **Example:** ```dart final result = instance.startPosition(); ``` **Returns:** `Point` ###### endPosition() [Section titled “endPosition()”](#endposition) Return the end `Point` (row, column). **Signature:** ```dart Future endPosition() ``` **Example:** ```dart final result = instance.endPosition(); ``` **Returns:** `Point` ###### isNamed() [Section titled “isNamed()”](#isnamed) True when this node is named (not punctuation/whitespace). **Signature:** ```dart Future isNamed() ``` **Example:** ```dart final result = instance.isNamed(); ``` **Returns:** `bool` ###### isError() [Section titled “isError()”](#iserror) True when this is an error node. **Signature:** ```dart Future isError() ``` **Example:** ```dart final result = instance.isError(); ``` **Returns:** `bool` ###### isMissing() [Section titled “isMissing()”](#ismissing) True when this is a missing-token node. **Signature:** ```dart Future isMissing() ``` **Example:** ```dart final result = instance.isMissing(); ``` **Returns:** `bool` ###### isExtra() [Section titled “isExtra()”](#isextra) True when this is an “extra” node (e.g. a comment). **Signature:** ```dart Future isExtra() ``` **Example:** ```dart final result = instance.isExtra(); ``` **Returns:** `bool` ###### hasError() [Section titled “hasError()”](#haserror) True when this node or any descendant is an error. **Signature:** ```dart Future hasError() ``` **Example:** ```dart final result = instance.hasError(); ``` **Returns:** `bool` ###### parent() [Section titled “parent()”](#parent) Return this node’s parent, if any. **Signature:** ```dart Future parent() ``` **Example:** ```dart final result = instance.parent(); ``` **Returns:** `Node?` ###### child() [Section titled “child()”](#child) Return the i-th child of this node, if any. **Signature:** ```dart Future child(int index) ``` **Example:** ```dart final result = instance.child(42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | ----- | -------- | ----------- | | `index` | `int` | Yes | The index | **Returns:** `Node?` ###### childCount() [Section titled “childCount()”](#childcount) Total number of children (including unnamed). **Signature:** ```dart Future childCount() ``` **Example:** ```dart final result = instance.childCount(); ``` **Returns:** `PlatformInt64` ###### namedChild() [Section titled “namedChild()”](#namedchild) Return the i-th named child of this node, if any. **Signature:** ```dart Future namedChild(int index) ``` **Example:** ```dart final result = instance.namedChild(42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | ----- | -------- | ----------- | | `index` | `int` | Yes | The index | **Returns:** `Node?` ###### namedChildCount() [Section titled “namedChildCount()”](#namedchildcount) Number of named children of this node. **Signature:** ```dart Future namedChildCount() ``` **Example:** ```dart final result = instance.namedChildCount(); ``` **Returns:** `PlatformInt64` ###### childByFieldName() [Section titled “childByFieldName()”](#childbyfieldname) Look up a child by its grammar-defined field name. **Signature:** ```dart Future childByFieldName(String name) ``` **Example:** ```dart final result = instance.childByFieldName("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Node?` ###### toSexp() [Section titled “toSexp()”](#tosexp) Return the S-expression form of this node’s subtree. **Signature:** ```dart Future toSexp() ``` **Example:** ```dart final result = instance.toSexp(); ``` **Returns:** `String` ###### walk() [Section titled “walk()”](#walk) Return a `TreeCursor` positioned at this node. **Signature:** ```dart Future walk() ``` **Example:** ```dart final result = instance.walk(); ``` **Returns:** `TreeCursor` *** #### PackConfig [Section titled “PackConfig”](#packconfig) Configuration for the tree-sitter language pack. Controls cache directory and which languages to pre-download. Can be loaded from a TOML file, constructed programmatically, or passed as a dict/object from language bindings. | Field | Type | Default | Description | | ----------- | --------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cacheDir` | `String?` | `null` | Override the BASE directory the parser cache lives under. This is a base, not the final library path: the crate appends `tree-sitter-language-pack/v{version}/libs` to it, exactly as it does to the platform default. So `cache_dir = "/tmp/my-parsers"` resolves to `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`. The suffix is not cosmetic. It keeps the whole cache tree — manifest, bundles and lock file included — inside a directory this library owns and versions. Earlier releases used this path verbatim, which put those files in the configured directory’s PARENT and let a cache built by one crate version be reused by another. Default base: the platform cache dir, e.g. `~/.cache` on Linux. | | `languages` | `List?` | `[]` | Languages to pre-download on init. Each entry is a language name (e.g. `"python"`, `"rust"`). | | `groups` | `List?` | `[]` | Language groups to pre-download. Group names come from the remote manifest, so the valid set is not fixed by this library; the published manifest currently defines only `"all"`. Call `manifest_groups` to enumerate them. An unknown name makes `init` fail. | *** #### Parser [Section titled “Parser”](#parser) A tree-sitter parser configured for one language at a time. ##### Methods [Section titled “Methods”](#methods-3) ###### create() [Section titled “create()”](#create-2) Construct a new parser with no language set and no parse limits. Call `Parser.set_language` before parsing. Limits are opt-in via `set_max_source_bytes` and `set_parse_timeout_ms`; both default to unbounded so that existing callers are unaffected. **Signature:** ```dart static Future create() ``` **Example:** ```dart final result = Parser.create(); ``` **Returns:** `Parser` ###### setMaxSourceBytes() [Section titled “setMaxSourceBytes()”](#setmaxsourcebytes) Refuse to parse sources longer than `max_bytes`. `null` (the default) means no limit. Over-limit input makes `parse` and `parse_bytes` return `null` after emitting a `WARN`; input is never silently truncated. See `RECOMMENDED_MAX_SOURCE_BYTES`. **Signature:** ```dart Future setMaxSourceBytes({PlatformInt64? maxBytes}) ``` **Example:** ```dart instance.setMaxSourceBytes(42); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ---------------- | -------- | ------------- | | `maxBytes` | `PlatformInt64?` | No | The max bytes | **Returns:** No return value. ###### setParseTimeoutMs() [Section titled “setParseTimeoutMs()”](#setparsetimeoutms) Cancel a parse that exceeds `timeout_ms` milliseconds of wall clock. `null` (the default) means no budget. Cancellation runs through tree-sitter’s parse progress callback, so it is granular to that callback’s interval rather than exact. See `RECOMMENDED_PARSE_TIMEOUT_MS`. **Signature:** ```dart Future setParseTimeoutMs({int? timeoutMs}) ``` **Example:** ```dart instance.setParseTimeoutMs(42); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | ------ | -------- | -------------- | | `timeoutMs` | `int?` | No | The timeout ms | **Returns:** No return value. ###### setLanguage() [Section titled “setLanguage()”](#setlanguage) Configure the parser to use the language identified by name (e.g. `"python"`). Resolves the language through the global registry — auto-downloading if necessary, when the `download` feature is enabled. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language ABI is incompatible. **Signature:** ```dart Future setLanguage(String name) ``` **Example:** ```dart instance.setLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** No return value. **Errors:** Throws `Error`. ###### parse() [Section titled “parse()”](#parse) Parse a UTF-8 source string. Returns `null` if no language is set, if the parse was cancelled by the configured timeout, or if the source exceeds the configured size limit. Each non-parse outcome is logged, so an empty result is never silent. ###### Concurrency [Section titled “Concurrency”](#concurrency) Parsing runs fully in parallel across threads for almost every language — no lock is taken. The exception is the small set of grammars whose external scanner keeps mutable process-global state (currently just `properties`): parses of that language are serialized against each other through an internal per-language lock, so that concurrent threads can’t corrupt shared scanner state. Every other language is unaffected by that lock and never waits on it. **Signature:** ```dart Future parse(String source) ``` **Example:** ```dart final result = instance.parse("value"); ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------- | -------- | ----------- | | `source` | `String` | Yes | The source | **Returns:** `Tree?` ###### parseBytes() [Section titled “parseBytes()”](#parsebytes) Parse a raw byte slice. Same outcomes as `parse`, including the concurrency behaviour documented there. **Signature:** ```dart Future parseBytes(Uint8List source) ``` **Example:** ```dart final result = instance.parseBytes(Uint8List.fromList([100, 97, 116, 97])); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ----------- | -------- | ----------- | | `source` | `Uint8List` | Yes | The source | **Returns:** `Tree?` ###### reset() [Section titled “reset()”](#reset) Reset internal state. The next call to `parse` will not be incremental. **Signature:** ```dart Future reset() ``` **Example:** ```dart instance.reset(); ``` **Returns:** No return value. *** #### Point [Section titled “Point”](#point) A source position — row + column, zero-indexed. | Field | Type | Default | Description | | -------- | --------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `row` | `PlatformInt64` | — | Zero-indexed row number. | | `column` | `PlatformInt64` | — | Zero-indexed column, counted in **bytes** from the start of the row. This is `tree_sitter.Point.column` verbatim, and tree-sitter defines it as a byte offset — not characters, and not UTF-16 code units. Measured on a row of the form `x = ''` where `` is a single 4-byte character (an emoji), the string node reports columns `4..10`, identical to its byte range; the character columns would be `4..7` and the UTF-16 columns `4..8`. Anything that builds LSP positions (UTF-16) or editor caret columns (characters) from this field is silently wrong on every row containing a non-ASCII byte, and must re-measure the row against the source text instead. Earlier releases documented this field as UTF-16 code units; that was never what the value contained. | *** #### ProcessConfig [Section titled “ProcessConfig”](#processconfig) Configuration for the `process()` function. Controls which analysis features are enabled and whether chunking is performed. | Field | Type | Default | Description | | ---------------- | ---------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String` | `""` | Language name (required). | | `structure` | `bool` | `true` | Extract structural items (functions, classes, etc.). Default: true. | | `imports` | `bool` | `true` | Extract import statements. Default: true. | | `exports` | `bool` | `true` | Extract export statements. Default: true. | | `comments` | `bool` | `false` | Extract comments. Default: false. | | `docstrings` | `bool` | `false` | Extract docstrings. Default: false. | | `symbols` | `bool` | `false` | Extract symbol definitions. Default: false. | | `diagnostics` | `bool` | `false` | Include parse diagnostics. Default: false. | | `chunkMaxSize` | `PlatformInt64?` | `null` | Maximum chunk size in bytes. `null` disables chunking. `Some(0)` is rejected by `ProcessConfig.validate` with `Error.InvalidRange`. A zero-sized chunk limit previously produced an empty chunk list and silently discarded the whole source; use `null` to mean “do not chunk”. | | `dataExtraction` | `bool` | `false` | Extract hierarchical key/value data tree from data-format files. Default: false. When `true`, `ProcessResult.data` is populated with a `DataNode` tree for supported languages: JSON, YAML, TOML, `.properties`, HCL/HOCON, INI, editorconfig, KDL, CUE, CSV, PSV, PO, nginx config, Caddy config, XML, and DTD. For languages outside this set the field is left as `null`. | | `maxSourceBytes` | `PlatformInt64?` | `null` | Reject source longer than this many bytes instead of parsing it. Default: `null` (unbounded). Tree-sitter allocates and walks proportionally to input size, so an unbounded parse of attacker-supplied input is a denial-of-service vector. The default stays unbounded for backward compatibility; services handling untrusted input should opt in, e.g. with `RECOMMENDED_MAX_SOURCE_BYTES`. Exceeding the limit fails the call with `Error.InvalidRange` — the source is never silently truncated. | | `parseTimeoutMs` | `int?` | `null` | Wall-clock budget for the parse step, in milliseconds. Default: `null` (no timeout). Enforced through tree-sitter’s parse progress callback, which the parser invokes periodically; cancellation is therefore granular to that callback interval rather than exact. A parse that exceeds the budget fails with `Error.ParseTimeout`. | *** #### ProcessResult [Section titled “ProcessResult”](#processresult) Complete analysis result from processing a source file. Contains metrics, structural analysis, imports/exports, comments, docstrings, symbols, diagnostics, and optionally chunked code segments. Fields are populated based on the `ProcessConfig` flags. | Field | Type | Default | Description | | ------------- | --------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String` | — | The language name used to parse the source file. | | `metrics` | `FileMetrics` | — | File-level metrics (line counts, byte size, error count). | | `structure` | `List` | `[]` | Top-level structural items (functions, classes, etc.). | | `imports` | `List` | `[]` | Import statements extracted from the source. | | `exports` | `List` | `[]` | Export statements extracted from the source. | | `comments` | `List` | `[]` | Comments extracted from the source. | | `docstrings` | `List` | `[]` | Docstrings extracted from the source. | | `symbols` | `List` | `[]` | Symbol definitions (variables, types, functions) extracted from the source. | | `diagnostics` | `List` | `[]` | Parse diagnostics (syntax errors, missing nodes) from tree-sitter. | | `chunks` | `List` | `[]` | Syntax-aware code chunks produced when chunking is enabled. | | `data` | `DataNode?` | `null` | Hierarchical data tree extracted when `config.data_extraction` is `true`. Populated for supported data-format languages (JSON, YAML, TOML, properties, HCL, INI, XML, CSV, and more). `null` when `data_extraction` is `false` (the default) or when the language is not a recognised data format. See `DataNode` for the shape of the returned tree. | *** #### Span [Section titled “Span”](#span) Byte and line/column range in source code. Represents both byte offsets (for slicing) and human-readable line/column positions (for display and diagnostics). | Field | Type | Default | Description | | ------------- | --------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `startByte` | `PlatformInt64` | — | Inclusive start byte offset in the source. | | `endByte` | `PlatformInt64` | — | Exclusive end byte offset in the source. | | `startLine` | `PlatformInt64` | — | Zero-indexed line number of the span’s start. | | `startColumn` | `PlatformInt64` | — | Zero-indexed column of the span’s start, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | | `endLine` | `PlatformInt64` | — | Zero-indexed line number of the span’s end. | | `endColumn` | `PlatformInt64` | — | Zero-indexed column of the span’s end, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | *** #### StructureItem [Section titled “StructureItem”](#structureitem) A structural item (function, class, struct, etc.) in source code. | Field | Type | Default | Description | | ------------ | --------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `kind` | `StructureKind` | `StructureKind.function` | The kind of structural item. | | `name` | `String?` | `null` | The declared name of the item, if present. | | `visibility` | `String?` | `null` | Visibility modifier (e.g., `"pub"`, `"public"`, `"private"`). | | `span` | `Span` | — | Source span covering the entire item declaration. | | `children` | `List` | `[]` | Nested structural items (e.g., methods within a class). | | `decorators` | `List` | `[]` | Decorator or attribute names applied to the item. **Reserved: not yet populated.** Always empty, for every language. Recognising a decorator requires per-language grammar knowledge (a Python `decorated_definition` wrapper, Java/C# annotations, Rust attributes each have a different shape), which no extractor here implements yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | | `docComment` | `String?` | `null` | Documentation comment attached to the item, if any. The text of the comment (or run of comments) immediately preceding the item, with no blank line in between, when that comment is classified as a doc comment. Multiple adjacent single-line doc comments (Rust `///`) are joined with `\n` in source order. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`). `null` for every other language, and for a preceding comment that is not in doc-comment form (a plain `#` comment in Python, Ruby, or Elixir) — Python’s docstring convention is captured separately, as `DocstringInfo`, not through this field. | | `signature` | `String?` | `null` | Full signature text of the item (e.g., function parameters and return type). The item’s own source text from its start up to the start of its body (see `StructureItem.body_span`), trimmed of trailing whitespace — for example `fn add(a: i32, b: i32) -> i32` for a Rust function whose body is `{ a + b }`. `null` only when that text is empty, which does not happen for any item `StructureKind` currently reports. Populated for every language and kind this library extracts structure for, since it is derived from `body_span`’s boundary rather than per-language syntax. | | `bodySpan` | `Span?` | `null` | Source span covering only the body of the item, if distinct from the declaration. | *** #### SymbolInfo [Section titled “SymbolInfo”](#symbolinfo) A symbol (variable, function, type, etc.) extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------ | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `String` | — | The name of the symbol. | | `kind` | `SymbolKind` | `SymbolKind.variable` | The kind of symbol (variable, function, class, etc.). | | `span` | `Span` | — | Source span covering the symbol definition. | | `typeAnnotation` | `String?` | `null` | Explicit type annotation, if present in the source. | | `doc` | `String?` | `null` | Documentation comment immediately preceding this symbol, resolved by the same walk `StructureItem.doc_comment` uses (see `doc_comment_at`) — never hard-coded `null`. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`) — the languages whose comment classification recognizes a doc-kind comment. `null` for every other language (e.g. Python, Go, Ruby, which have no doc-kind comment classification), and also `null` when a symbol in a supported language simply has no doc comment immediately above it. | *** #### Tree [Section titled “Tree”](#tree) A parsed syntax tree. Cheap to clone (refcount bump). ##### Methods [Section titled “Methods”](#methods-4) ###### rootNode() [Section titled “rootNode()”](#rootnode) Return the root `Node` of this tree. **Signature:** ```dart Future rootNode() ``` **Example:** ```dart final result = instance.rootNode(); ``` **Returns:** `Node` ###### walk() [Section titled “walk()”](#walk-1) Return a `TreeCursor` positioned at the root. **Signature:** ```dart Future walk() ``` **Example:** ```dart final result = instance.walk(); ``` **Returns:** `TreeCursor` *** #### TreeCursor [Section titled “TreeCursor”](#treecursor) A cursor for traversing a `Tree`. ##### Methods [Section titled “Methods”](#methods-5) ###### node() [Section titled “node()”](#node-1) Return the `Node` at the cursor’s current position. **Signature:** ```dart Future node() ``` **Example:** ```dart final result = instance.node(); ``` **Returns:** `Node` ###### gotoFirstChild() [Section titled “gotoFirstChild()”](#gotofirstchild) Move the cursor to the first child of the current node. Returns `true` if a child existed. **Signature:** ```dart Future gotoFirstChild() ``` **Example:** ```dart final result = instance.gotoFirstChild(); ``` **Returns:** `bool` ###### gotoParent() [Section titled “gotoParent()”](#gotoparent) Move the cursor to the parent of the current node. Returns `true` if a parent existed. **Signature:** ```dart Future gotoParent() ``` **Example:** ```dart final result = instance.gotoParent(); ``` **Returns:** `bool` ###### gotoNextSibling() [Section titled “gotoNextSibling()”](#gotonextsibling) Move the cursor to the next sibling of the current node. Returns `true` if a sibling existed. **Signature:** ```dart Future gotoNextSibling() ``` **Example:** ```dart final result = instance.gotoNextSibling(); ``` **Returns:** `bool` ###### fieldName() [Section titled “fieldName()”](#fieldname) Return the field name for the current node, if any. **Signature:** ```dart Future fieldName() ``` **Example:** ```dart final result = instance.fieldName(); ``` **Returns:** `String?` *** ### Enums [Section titled “Enums”](#enums) #### DataNodeKind [Section titled “DataNodeKind”](#datanodekind) The kind of a data node extracted from a data-format file. Classifies each node in the hierarchical `DataNode` tree returned when `data_extraction` is enabled on `ProcessConfig`. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract) Unit variants serialize as a bare string (`"KeyValue"`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ---------- | -------------------------------------------------------------------------------------------------------------------- | | `KeyValue` | A key/value pair or mapping (json/toml/properties/yaml/hcl/cue/kdl pair, or a wrapper “object”/“mapping” container). | | `Element` | An XML element with a tag name in `key` and attributes in `attributes`. | | `Sequence` | A positional sequence item (JSON array element, YAML block sequence item, CSV/PSV row or cell). | *** #### StructureKind [Section titled “StructureKind”](#structurekind) The kind of structural item found in source code. Categorizes top-level and nested declarations such as functions, classes, structs, enums, traits, and more. Use `Other` for language-specific constructs that do not fit a standard category. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-1) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | ---------------------------------------------------------------------------------------------- | | `Function` | A free-standing or associated function. | | `Method` | A method defined inside a class, struct, trait, or impl block. | | `Class` | A class definition. | | `Struct` | A struct definition. | | `Interface` | An interface or protocol definition. | | `Enum` | An enum definition. | | `Module` | A module or package declaration. | | `Trait` | A trait definition. | | `Impl` | An impl block (Rust) or similar implementation block. | | `Namespace` | A namespace declaration. | | `Other` | A language-specific construct that does not fit any standard category. — Fields: `0`: `String` | *** #### CommentKind [Section titled “CommentKind”](#commentkind) The kind of a comment found in source code. Distinguishes between single-line comments, block (multi-line) comments, and documentation comments. | Value | Description | | ------- | --------------------------------------------------------------------- | | `Line` | A single-line comment (e.g., `// ...` or `# ...`). | | `Block` | A block or multi-line comment using slash-star delimiters. | | `Doc` | A documentation comment such as `/// ...` or slash-double-star block. | *** #### DocstringFormat [Section titled “DocstringFormat”](#docstringformat) The format of a docstring extracted from source code. Identifies the docstring convention used, which varies by language (e.g., Python triple-quoted strings, JSDoc, Rustdoc `///` comments). ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-2) Unit variants serialize as a bare string (`"JSDoc"`); the `Other` variant serializes as a single-keyed object (`{"Other": "rst"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ------------------- | -------------------------------------------------------------------------------------------------- | | `PythonTripleQuote` | Python triple-quoted string docstring (`"""..."""`). | | `JsDoc` | JavaScript/TypeScript JSDoc block comment (opens with two stars, closes with star-slash). | | `Rustdoc` | Rust `///` or `//!` doc comment. | | `GoDoc` | Go doc comment (a comment block immediately preceding a declaration). | | `JavaDoc` | Java Javadoc block comment (opens with two stars, closes with star-slash). | | `Other` | A language-specific docstring format not covered by the standard variants. — Fields: `0`: `String` | *** #### ExportKind [Section titled “ExportKind”](#exportkind) The kind of an export statement found in source code. Covers named exports, default exports, and re-exports from other modules. | Value | Description | | ---------- | -------------------------------------------------------------------- | | `Named` | A named export (e.g., `export { foo }`). | | `Default` | A default export (e.g., `export default foo`). | | `ReExport` | A re-export from another module (e.g., `export { foo } from 'bar'`). | *** #### SymbolKind [Section titled “SymbolKind”](#symbolkind) The kind of a symbol definition found in source code. Categorizes symbol definitions such as variables, constants, functions, classes, types, interfaces, enums, and modules. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-3) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | --------------------------------------------------------------------------- | | `Variable` | A variable binding. | | `Constant` | A constant (immutable binding). | | `Function` | A function definition. | | `Class` | A class definition. | | `Type` | A type alias or typedef. | | `Interface` | An interface definition. | | `Enum` | An enum definition. | | `Module` | A module declaration. | | `Other` | A symbol kind not covered by the standard variants. — Fields: `0`: `String` | *** #### DiagnosticSeverity [Section titled “DiagnosticSeverity”](#diagnosticseverity) Severity level of a diagnostic produced during parsing. Used to classify parse errors, warnings, and informational messages found in the syntax tree. | Value | Description | | --------- | --------------------------------------------------------------- | | `Error` | A parse error (e.g., an `ERROR` or `MISSING` node in the tree). | | `Warning` | A warning-level diagnostic. | | `Info` | An informational diagnostic. | *** ### Errors [Section titled “Errors”](#errors) #### Error [Section titled “Error”](#error) Errors that can occur when using the tree-sitter language pack. Covers language lookup failures, parse errors, query errors, and I/O issues. Feature-gated variants are included when `config`, `download`, or related features are enabled. ##### Matching on `Error` [Section titled “Matching on Error”](#matching-on-error) The set of variants is not stable: new failure modes are added in minor releases, and `Io`, `Json`, and `Toml` exist only under certain feature combinations, so the variant set a downstream crate sees depends on which features it enables. Downstream `match`es must therefore carry a `_` arm; `#[non_exhaustive]` makes the compiler enforce that instead of letting a feature change silently break a build. ##### C ABI error codes [Section titled “C ABI error codes”](#c-abi-error-codes) Each variant alef can see carries an explicit `alef(error_code = N)` allocation that becomes a member of the generated `AlefFfiErrorCode` C enum. These numbers are a public ABI contract: **an allocated number is never reused after its variant is removed**, and a variant’s number never changes, because C callers compare against the value, not the name. New variants take the next free number. 0-4 are reserved by alef, so allocation starts at 100. An unannotated variant is emitted as the unknown code rather than as itself, which silently flattens the taxonomy — annotate every new variant. | Variant | Description | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `LanguageNotFound` | The requested language name (or alias) was not found in the registry. | | `DynamicLoad` | A dynamic shared library could not be loaded at runtime. | | `NullLanguagePointer` | The tree-sitter language function returned a null pointer for the given language name. | | `ParserSetup` | The language could not be applied to the parser (e.g., ABI version mismatch). | | `LockPoisoned` | An internal `RwLock` or `Mutex` was poisoned by a previous panic. | | `Config` | A configuration file or value was invalid or could not be applied. | | `ParseFailed` | The tree-sitter parser returned no tree for the given source input. | | `ParseTimeout` | The parse was cancelled because it exceeded its configured wall-clock budget. Raised only when a budget is configured — see `ProcessConfig.parse_timeout_ms`, which defaults to `null`. | | `QueryError` | A tree-sitter query could not be compiled or executed. | | `InvalidRange` | A byte range was invalid (e.g., end before start, or out of bounds). | | `Download` | A parser download from GitHub releases failed. | | `ChecksumMismatch` | The downloaded file’s SHA-256 digest did not match the manifest’s expected value. | | `CacheLock` | The cross-process download cache lock file could not be acquired or created. | *** # Elixir API Reference ## Elixir API Reference v1.16.1 [Section titled “Elixir API Reference v1.16.1”](#elixir-api-reference-v1161) ### Functions [Section titled “Functions”](#functions) #### detect\_language\_from\_extension() [Section titled “detect\_language\_from\_extension()”](#detect_language_from_extension) Detect language name from a file extension (without leading dot). Returns `nil` for unrecognized extensions. The match is case-insensitive. **Signature:** ```elixir @spec detect_language_from_extension(ext) :: {:ok, term()} | {:error, term()} def detect_language_from_extension(ext) ``` **Example:** ```elixir {:ok, result} = detect_language_from_extension("value") ``` **Parameters:** | Name | Type | Required | Description | | ----- | ------------ | -------- | ----------- | | `ext` | `String.t()` | Yes | The ext | **Returns:** `String.t() | nil` *** #### detect\_language\_from\_path() [Section titled “detect\_language\_from\_path()”](#detect_language_from_path) Detect language name from a file path. Extracts the file extension and looks it up. Returns `nil` if the path has no extension or the extension is not recognized. **Signature:** ```elixir @spec detect_language_from_path(path) :: {:ok, term()} | {:error, term()} def detect_language_from_path(path) ``` **Example:** ```elixir {:ok, result} = detect_language_from_path("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------ | -------- | ---------------- | | `path` | `String.t()` | Yes | Path to the file | **Returns:** `String.t() | nil` *** #### detect\_language\_from\_content() [Section titled “detect\_language\_from\_content()”](#detect_language_from_content) Detect language name from file content using the shebang line (`#!`). Inspects only the first line of `content`. If it begins with `#!`, the interpreter name is extracted and mapped to a language name. Handles common patterns: * `#!/usr/bin/env python3` → `"python"` * `#!/bin/bash` → `"bash"` * `#!/usr/bin/env node` → `"javascript"` The `-S` flag accepted by some `env` implementations is skipped automatically. Version suffixes (e.g. `python3.11`, `ruby3.2`) are stripped before matching. A leading UTF-8 BOM (`U+FEFF`) is skipped before the `#!` check, so a BOM-prefixed script is still detected by its shebang. Returns `nil` when content does not start with `#!` (after stripping a leading BOM), the shebang is malformed, or the interpreter is not recognised. **Signature:** ```elixir @spec detect_language_from_content(content) :: {:ok, term()} | {:error, term()} def detect_language_from_content(content) ``` **Example:** ```elixir {:ok, result} = detect_language_from_content("value") ``` **Parameters:** | Name | Type | Required | Description | | --------- | ------------ | -------- | ---------------------- | | `content` | `String.t()` | Yes | The content to process | **Returns:** `String.t() | nil` *** #### get\_highlights\_query() [Section titled “get\_highlights\_query()”](#get_highlights_query) Get the highlights query for a language, if bundled. Returns the contents of `highlights.scm` as a static string, or `nil` if no highlights query is bundled for this language. **Signature:** ```elixir @spec get_highlights_query(language) :: {:ok, term()} | {:error, term()} def get_highlights_query(language) ``` **Example:** ```elixir {:ok, result} = get_highlights_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------------ | -------- | ------------ | | `language` | `String.t()` | Yes | The language | **Returns:** `String.t() | nil` *** #### get\_injections\_query() [Section titled “get\_injections\_query()”](#get_injections_query) Get the injections query for a language, if bundled. Returns the contents of `injections.scm` as a static string, or `nil` if no injections query is bundled for this language. **Signature:** ```elixir @spec get_injections_query(language) :: {:ok, term()} | {:error, term()} def get_injections_query(language) ``` **Example:** ```elixir {:ok, result} = get_injections_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------------ | -------- | ------------ | | `language` | `String.t()` | Yes | The language | **Returns:** `String.t() | nil` *** #### get\_locals\_query() [Section titled “get\_locals\_query()”](#get_locals_query) Get the locals query for a language, if bundled. Returns the contents of `locals.scm` as a static string, or `nil` if no locals query is bundled for this language. **Signature:** ```elixir @spec get_locals_query(language) :: {:ok, term()} | {:error, term()} def get_locals_query(language) ``` **Example:** ```elixir {:ok, result} = get_locals_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------------ | -------- | ------------ | | `language` | `String.t()` | Yes | The language | **Returns:** `String.t() | nil` *** #### get\_tags\_query() [Section titled “get\_tags\_query()”](#get_tags_query) Get the tags query for a language, if bundled. Returns the contents of `tags.scm` as a static string, or `nil` if no tags query is bundled for this language. **Signature:** ```elixir @spec get_tags_query(language) :: {:ok, term()} | {:error, term()} def get_tags_query(language) ``` **Example:** ```elixir {:ok, result} = get_tags_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------------ | -------- | ------------ | | `language` | `String.t()` | Yes | The language | **Returns:** `String.t() | nil` *** #### get\_indents\_query() [Section titled “get\_indents\_query()”](#get_indents_query) Get the indents query for a language, if bundled. Returns the contents of `indents.scm` (used for auto-indentation) as a static string, or `nil` if no indents query is bundled for this language. **Signature:** ```elixir @spec get_indents_query(language) :: {:ok, term()} | {:error, term()} def get_indents_query(language) ``` **Example:** ```elixir {:ok, result} = get_indents_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------------ | -------- | ------------ | | `language` | `String.t()` | Yes | The language | **Returns:** `String.t() | nil` *** #### get\_folds\_query() [Section titled “get\_folds\_query()”](#get_folds_query) Get the folds query for a language, if bundled. Returns the contents of `folds.scm` (used for code folding) as a static string, or `nil` if no folds query is bundled for this language. **Signature:** ```elixir @spec get_folds_query(language) :: {:ok, term()} | {:error, term()} def get_folds_query(language) ``` **Example:** ```elixir {:ok, result} = get_folds_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------------ | -------- | ------------ | | `language` | `String.t()` | Yes | The language | **Returns:** `String.t() | nil` *** #### get\_language() [Section titled “get\_language()”](#get_language) Get a tree-sitter `Language` by name using the global registry. Resolves language aliases (e.g., `"shell"` maps to `"bash"`). When the `download` feature is enabled (default), automatically downloads the parser from GitHub releases if not found locally. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.Download` if auto-download fails. **Signature:** ```elixir @spec get_language(name) :: {:ok, term()} | {:error, term()} def get_language(name) ``` **Example:** ```elixir {:ok, result} = get_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------ | -------- | ----------- | | `name` | `String.t()` | Yes | The name | **Returns:** `Language` **Errors:** Returns `{:error, reason}` *** #### get\_parser() [Section titled “get\_parser()”](#get_parser) Get a `Parser` pre-configured for the given language. This is a convenience function that calls `get_language` and configures a new parser in one step. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language cannot be applied to the parser. **Signature:** ```elixir @spec get_parser(name) :: {:ok, term()} | {:error, term()} def get_parser(name) ``` **Example:** ```elixir {:ok, result} = get_parser("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------ | -------- | ----------- | | `name` | `String.t()` | Yes | The name | **Returns:** `Parser` **Errors:** Returns `{:error, reason}` *** #### detect\_language() [Section titled “detect\_language()”](#detect_language) Detect language name from a file path or extension. This compatibility alias matches the pre-Alef Python binding API. **Signature:** ```elixir @spec detect_language(path) :: {:ok, term()} | {:error, term()} def detect_language(path) ``` **Example:** ```elixir {:ok, result} = detect_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------ | -------- | ---------------- | | `path` | `String.t()` | Yes | Path to the file | **Returns:** `String.t() | nil` *** #### available\_languages() [Section titled “available\_languages()”](#available_languages) List all available language names (sorted, deduplicated, includes aliases). Returns names of both statically compiled and dynamically loadable languages, plus any configured aliases. **Signature:** ```elixir @spec available_languages() :: {:ok, term()} | {:error, term()} def available_languages() ``` **Example:** ```elixir {:ok, result} = available_languages() ``` **Returns:** `list(String.t())` *** #### has\_language() [Section titled “has\_language()”](#has_language) Check if a language is available by name or alias. Returns `true` if the language can be loaded (statically compiled, dynamically available, or a known alias for one of these). **Signature:** ```elixir @spec has_language(name) :: {:ok, term()} | {:error, term()} def has_language(name) ``` **Example:** ```elixir {:ok, result} = has_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------ | -------- | ----------- | | `name` | `String.t()` | Yes | The name | **Returns:** `boolean()` *** #### language\_count() [Section titled “language\_count()”](#language_count) Return the number of available languages. Includes statically compiled languages, dynamically loadable languages, and aliases. **Signature:** ```elixir @spec language_count() :: {:ok, term()} | {:error, term()} def language_count() ``` **Example:** ```elixir {:ok, result} = language_count() ``` **Returns:** `integer()` *** #### process() [Section titled “process()”](#process) Process source code and extract file intelligence using the global registry. Parses the source with tree-sitter and extracts metrics, structure, imports, exports, comments, docstrings, symbols, diagnostics, and/or chunks based on the flags set in `ProcessConfig`. **Errors:** Returns `Error.InvalidRange` if the config carries a zero-valued limit or the source exceeds `ProcessConfig.max_source_bytes`, `Error.ParseTimeout` if the parse exceeds `ProcessConfig.parse_timeout_ms`, `Error.LanguageNotFound` if the language is unknown, or `Error.ParseFailed` if parsing yields no tree. **Signature:** ```elixir @spec process(source, config) :: {:ok, term()} | {:error, term()} def process(source, config) ``` **Example:** ```elixir {:ok, result} = process("value", %{}) ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `String.t()` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Returns `{:error, reason}` *** #### init() [Section titled “init()”](#init) Initialize the language pack with the given configuration. Applies any custom cache directory, then downloads all languages and groups specified in the config. This is the recommended entry point when you want to pre-warm the cache before use. **Errors:** Returns an error if configuration cannot be applied or if downloads fail. **Signature:** ```elixir @spec init(config) :: {:ok, term()} | {:error, term()} def init(config) ``` **Example:** ```elixir :ok = init(%{}) ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Returns `{:error, reason}` *** #### configure() [Section titled “configure()”](#configure) Apply download configuration without downloading anything. Use this to set a custom cache directory before the first call to `get_language` or any download function. Changing the cache dir after languages have been registered has no effect on already-loaded languages. `PackConfig.cache_dir` is a BASE directory, not the final libs path: this crate appends `tree-sitter-language-pack/v{version}/libs` to it, the same suffix applied to the platform default cache directory. In the example below, files actually land under `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`, never directly in `/tmp/my-parsers/`. Call `cache_dir` to read back the resolved, fully-suffixed path. **Errors:** Returns an error if the lock cannot be acquired. **Signature:** ```elixir @spec configure(config) :: {:ok, term()} | {:error, term()} def configure(config) ``` **Example:** ```elixir :ok = configure(%{}) ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Returns `{:error, reason}` *** #### download() [Section titled “download()”](#download) Download specific languages to the local cache. Returns the number of distinct languages available after the call. Already compiled or cached languages are included in the count. Aliases are resolved before counting, so `["shell", "bash"]` names one language and returns 1. **Errors:** Returns an error if any language is not available in the manifest or if the download fails. **Signature:** ```elixir @spec download(names) :: {:ok, term()} | {:error, term()} def download(names) ``` **Example:** ```elixir {:ok, result} = download([]) ``` **Parameters:** | Name | Type | Required | Description | | ------- | ------------------ | -------- | ----------- | | `names` | `list(String.t())` | Yes | The names | **Returns:** `integer()` **Errors:** Returns `{:error, reason}` *** #### prefetch() [Section titled “prefetch()”](#prefetch) Prefetch grammars: download any not already loadable from disk, then load every requested language into the process registry so a subsequent hot loop only parses. Unlike `download()`, this does not trust in-memory availability — it downloads whenever a grammar is not actually loadable from disk (fixing the case where a known-but-not-downloaded grammar is reported present), then resolves and caches every requested language. Call it once, up front, before a parallel workload. **Errors:** Returns `Error.Download` if a required grammar cannot be fetched, or `Error.LanguageNotFound` if a requested name is unknown. **Signature:** ```elixir @spec prefetch(languages) :: {:ok, term()} | {:error, term()} def prefetch(languages) ``` **Example:** ```elixir :ok = prefetch([]) ``` **Parameters:** | Name | Type | Required | Description | | ----------- | ------------------ | -------- | ------------- | | `languages` | `list(String.t())` | Yes | The languages | **Returns:** No return value. **Errors:** Returns `{:error, reason}` *** #### download\_all() [Section titled “download\_all()”](#download_all) Download all available languages from the remote manifest. Downloads the platform bundle and extracts every library it contains. Languages that appear in the manifest but are absent from the bundle (e.g. grammars that failed to compile at release time) are silently skipped — they are not treated as an error. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns an error if the manifest cannot be fetched or the bundle download fails. **Signature:** ```elixir @spec download_all() :: {:ok, term()} | {:error, term()} def download_all() ``` **Example:** ```elixir {:ok, result} = download_all() ``` **Returns:** `integer()` **Errors:** Returns `{:error, reason}` *** #### download\_group() [Section titled “download\_group()”](#download_group) Download every language in a named group. Groups are defined by the remote manifest, not by this library, and let you ensure a curated set of related grammars in one call instead of listing each name to `download()`. Already-cached languages are skipped. Call `manifest_groups` to discover the group names the manifest actually defines. The published manifest currently defines a single group, `"all"`; earlier revisions of this documentation advertised `"web"`, `"data"`, and `"systems"`, which the manifest has never contained, so every call following that example failed. Do not hardcode a group name without checking. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns `Error.Download` if the manifest cannot be fetched, if the group is unknown — the message lists the groups the manifest defines — or if any constituent language fails to download. **Signature:** ```elixir @spec download_group(name) :: {:ok, term()} | {:error, term()} def download_group(name) ``` **Example:** ```elixir {:ok, result} = download_group("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------ | -------- | ----------- | | `name` | `String.t()` | Yes | The name | **Returns:** `integer()` **Errors:** Returns `{:error, reason}` *** #### manifest\_languages() [Section titled “manifest\_languages()”](#manifest_languages) Return all language names available in the remote manifest (371). Fetches (and caches) the remote manifest to discover the full list of downloadable languages. Use `downloaded_languages` to list what is already cached locally. **Errors:** Returns an error if the manifest cannot be fetched. **Signature:** ```elixir @spec manifest_languages() :: {:ok, term()} | {:error, term()} def manifest_languages() ``` **Example:** ```elixir {:ok, result} = manifest_languages() ``` **Returns:** `list(String.t())` **Errors:** Returns `{:error, reason}` *** #### manifest\_groups() [Section titled “manifest\_groups()”](#manifest_groups) Return the names of every language group the remote manifest defines, sorted. Group names are manifest data, not a compile-time constant of this library, so this is the only reliable way to learn what `download_group` and `PackConfig.groups` accept. The published manifest currently defines just `"all"`. **Errors:** Returns `Error.Download` if the manifest cannot be fetched. **Signature:** ```elixir @spec manifest_groups() :: {:ok, term()} | {:error, term()} def manifest_groups() ``` **Example:** ```elixir {:ok, result} = manifest_groups() ``` **Returns:** `list(String.t())` **Errors:** Returns `{:error, reason}` *** #### downloaded\_languages() [Section titled “downloaded\_languages()”](#downloaded_languages) Return languages that are already downloaded and cached locally. Does not perform any network requests. Returns an empty list if the cache directory does not exist or cannot be read. **Signature:** ```elixir @spec downloaded_languages() :: {:ok, term()} | {:error, term()} def downloaded_languages() ``` **Example:** ```elixir {:ok, result} = downloaded_languages() ``` **Returns:** `list(String.t())` *** #### clean\_cache() [Section titled “clean\_cache()”](#clean_cache) Delete all cached parser shared libraries. Resets the cache registration so the next call to `get_language` or a download function will re-register the (now empty) cache directory. **Errors:** Returns an error if the cache directory cannot be removed. **Signature:** ```elixir @spec clean_cache() :: {:ok, term()} | {:error, term()} def clean_cache() ``` **Example:** ```elixir :ok = clean_cache() ``` **Returns:** No return value. **Errors:** Returns `{:error, reason}` *** #### cache\_dir() [Section titled “cache\_dir()”](#cache_dir) Return the effective cache directory path. This is `{base}/tree-sitter-language-pack/v{version}/libs/`, where `{base}` is either the custom BASE directory set via `configure` / `init` (`PackConfig.cache_dir`) or the platform default cache directory — both are suffixed identically, so a custom `cache_dir` is never used as the final libs path. The default resolves to `~/.cache/tree-sitter-language-pack/v{version}/libs/` on a typical Unix system. **Errors:** Returns an error if no cache directory can be resolved: `version` is somehow invalid, or (with no custom `cache_dir` configured) the platform reports none and `TREE_SITTER_LANGUAGE_PACK_CACHE_DIR` is unset. This crate no longer falls back to the temporary directory for the latter case — see #101 H2. **Signature:** ```elixir @spec cache_dir() :: {:ok, term()} | {:error, term()} def cache_dir() ``` **Example:** ```elixir {:ok, result} = cache_dir() ``` **Returns:** `String.t()` **Errors:** Returns `{:error, reason}` *** ### Types [Section titled “Types”](#types) #### ByteRange [Section titled “ByteRange”](#byterange) A byte range — start (inclusive) to end (exclusive). | Field | Type | Default | Description | | ------- | ----------- | ------- | ---------------------------- | | `start` | `integer()` | — | Inclusive start byte offset. | | `end` | `integer()` | — | Exclusive end byte offset. | *** #### ChunkContext [Section titled “ChunkContext”](#chunkcontext) Metadata for a single chunk of source code. | Field | Type | Default | Description | | ----------------- | --------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String.t()` | — | Language name used to parse this chunk. | | `chunk_index` | `integer()` | — | Zero-indexed position of this chunk within the file’s chunk list. | | `total_chunks` | `integer()` | — | Total number of chunks the file was split into. | | `node_types` | `list(String.t())` | `[]` | Tree-sitter node kinds that appear at the top level of this chunk. | | `context_path` | `list(String.t())` | `[]` | Hierarchical path of enclosing structural items (e.g., `["MyClass", "my_method"]`). | | `symbols_defined` | `list(String.t())` | `[]` | Names of symbols defined within this chunk. | | `comments` | `list(CommentInfo)` | `[]` | Comments contained within this chunk. | | `docstrings` | `list(DocstringInfo)` | `[]` | Docstrings contained within this chunk. Populated only for Python — the same language for which `ProcessResult.docstrings` is populated, and by the same classifier. Always empty for every other language. | | `has_error_nodes` | `boolean()` | — | Whether this chunk contains any tree-sitter error nodes. | *** #### CodeChunk [Section titled “CodeChunk”](#codechunk) A chunk of source code with rich metadata. | Field | Type | Default | Description | | ------------ | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `content` | `String.t()` | — | The raw source text of this chunk. | | `start_byte` | `integer()` | — | Inclusive start byte offset of this chunk in the original source. | | `end_byte` | `integer()` | — | Exclusive end byte offset of this chunk in the original source. | | `start_line` | `integer()` | — | Zero-indexed start line of this chunk. | | `end_line` | `integer()` | — | Zero-indexed row of the last byte actually included in this chunk (inclusive — the same row a `Span.end_line` would report for a node ending on that byte). Computed the same way regardless of whether the source has a trailing newline: it is always the row of `end_byte - 1`, never a phantom row past the file’s real content. | | `metadata` | `ChunkContext` | — | Contextual metadata about this chunk. | *** #### CommentInfo [Section titled “CommentInfo”](#commentinfo) A comment extracted from source code. | Field | Type | Default | Description | | ----------------- | ------------------- | ------- | ----------------------------------------------------------------- | | `text` | `String.t()` | — | The raw text content of the comment. | | `kind` | `CommentKind` | `:line` | The kind of comment (line, block, or doc). | | `span` | `Span` | — | Source span covering the comment. | | `associated_node` | `String.t() \| nil` | `nil` | Name of the syntax node this comment is directly associated with. | *** #### DataAttribute [Section titled “DataAttribute”](#dataattribute) An XML-style attribute attached to an `Element` node. Populated only for `DataNodeKind.Element`; always empty for `KeyValue` and `Sequence` nodes. | Field | Type | Default | Description | | ------- | ------------ | ------- | --------------------------------------------------------------- | | `name` | `String.t()` | — | Attribute name (e.g. `"class"`, `"href"`). | | `value` | `String.t()` | — | Attribute value as a raw string (quotes stripped). | | `span` | `Span` | — | Source span covering the entire `name="value"` attribute token. | *** #### DataNode [Section titled “DataNode”](#datanode) A node in the hierarchical data tree produced by data-format extraction. When `ProcessConfig.data_extraction` is `true`, `ProcessResult.data` is populated with a root `DataNode` whose `children` mirror the structure of the parsed file. The `kind` field determines which other fields are meaningful: | `kind` | `key` | `value` | `attributes` | `children` | | ---------- | ------------------------- | ------------ | ------------ | -------------- | | `KeyValue` | key / mapping key / index | leaf value | empty | nested map | | `Element` | XML tag name | text content | XML attrs | child elements | | `Sequence` | positional index (`"0"`) | leaf value | empty | sub-items | | Field | Type | Default | Description | | ------------ | --------------------- | ------------ | ---------------------------------------------------------------------------------------------------- | | `kind` | `DataNodeKind` | `:key_value` | Whether this node is a key/value pair, XML element, or sequence item. | | `key` | `String.t() \| nil` | `nil` | Key, attribute name, tag name, or positional index (`"0"`, `"1"`, …). `nil` at the document root. | | `value` | `String.t() \| nil` | `nil` | Leaf scalar value, if any. `nil` for containers (objects, arrays, XML elements with child elements). | | `attributes` | `list(DataAttribute)` | `[]` | Attributes on element-shape nodes (XML `STag` attributes). Empty for all other kinds. | | `children` | `list(DataNode)` | `[]` | Children for nested containers and XML element bodies. | | `span` | `Span` | — | Source span covering this node in the original source file. | *** #### Diagnostic [Section titled “Diagnostic”](#diagnostic) A diagnostic (syntax error, missing node, etc.) from parsing. | Field | Type | Default | Description | | ---------- | -------------------- | -------- | ---------------------------------------------- | | `message` | `String.t()` | — | Human-readable description of the diagnostic. | | `severity` | `DiagnosticSeverity` | `:error` | Severity of the diagnostic. | | `span` | `Span` | — | Source span where the diagnostic was detected. | *** #### DocSection [Section titled “DocSection”](#docsection) A section within a docstring (e.g., Args, Returns, Raises). | Field | Type | Default | Description | | ------------- | ------------------- | ------- | ------------------------------------------------------- | | `kind` | `String.t()` | — | Section kind (e.g., `"args"`, `"returns"`, `"raises"`). | | `name` | `String.t() \| nil` | `nil` | Parameter or return value name, if applicable. | | `description` | `String.t()` | — | Description text for this section. | *** #### DocstringInfo [Section titled “DocstringInfo”](#docstringinfo) A docstring extracted from source code. | Field | Type | Default | Description | | ----------------- | ------------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | `String.t()` | — | The raw text of the docstring. | | `format` | `DocstringFormat` | `:python_triple_quote` | The docstring format (Python, JSDoc, Rustdoc, etc.). | | `span` | `Span` | — | Source span covering the docstring. | | `associated_item` | `String.t() \| nil` | `nil` | Name of the item this docstring documents. | | `parsed_sections` | `list(DocSection)` | `[]` | Parsed sections of the docstring (Args, Returns, Raises, etc.). **Reserved: not yet populated.** Always empty, for every `DocstringFormat`. Parsing a docstring body into sections requires implementing each convention’s own layout (Google/NumPy/reST style for Python, `@param`/`@returns` for JSDoc/Javadoc, and so on), which no extractor here does yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | *** #### DownloadManager [Section titled “DownloadManager”](#downloadmanager) Manages downloading and caching of pre-built parser shared libraries. ##### Functions [Section titled “Functions”](#functions-1) ###### new() [Section titled “new()”](#new) Create a new download manager for the given version. **Errors:** Returns `Error.Download` if `version` is empty, contains a path separator or `..`, or contains a character outside `[A-Za-z0-9.+-]` — see `validate_version` — or if no cache directory can be resolved (see `Self.default_cache_dir`). **Signature:** ```elixir def new(version) ``` **Example:** ```elixir {:ok, result} = DownloadManager.new("value") ``` **Parameters:** | Name | Type | Required | Description | | --------- | ------------ | -------- | ----------- | | `version` | `String.t()` | Yes | The version | **Returns:** `DownloadManager` **Errors:** Returns `{:error, reason}` ###### installed\_languages() [Section titled “installed\_languages()”](#installed_languages) List languages that are already downloaded and cached. Derived from the on-disk cache filenames, one canonical name per file, plus every alias that resolves to it (via `aliases_for`) — so this list agrees with the user-facing `LanguageRegistry.available_languages` about which names are “available”; both report `"shell"` once `bash` is cached, for example. A previous version reported canonical names only, which could never agree with `available_languages()`. See #107. Returns an empty list if the cache directory does not exist. If it exists but cannot be read (e.g. a permission error), also returns an empty list — changing this to a `Result` would be a breaking change across every language binding — but logs a `tracing.warn!` so the failure is not silently indistinguishable from “nothing installed”. **Signature:** ```elixir def installed_languages(obj) ``` **Example:** ```elixir {:ok, result} = instance.installed_languages() ``` **Returns:** `list(String.t())` ###### download\_all\_best\_effort() [Section titled “download\_all\_best\_effort()”](#download_all_best_effort) Download the platform bundle and extract every library file it contains. Unlike `Self.ensure_languages`, this does not check the manifest language list against archive contents — it simply extracts all `.so`/`.dylib`/`.dll` files from the bundle. Languages in the manifest that are missing from the archive are silently ignored rather than returning an error. Returns the number of library files extracted (including those already cached). **Signature:** ```elixir def download_all_best_effort(obj) ``` **Example:** ```elixir {:ok, result} = instance.download_all_best_effort() ``` **Returns:** `integer()` **Errors:** Returns `{:error, reason}` ###### clean\_cache() [Section titled “clean\_cache()”](#clean_cache-1) Remove all cached parser libraries. Acquires the cross-process lock so `clean_cache` cannot race a concurrent downloader (avoids Windows sharing-violation errors against an in-flight bundle write). The `.download.lock` file itself is **not** removed — it is permanent infrastructure; deleting it could allow a concurrent process that already opened the file to continue holding a stale lock handle while a new process opens a fresh inode, breaking the mutual-exclusion guarantee. **Signature:** ```elixir def clean_cache(obj) ``` **Example:** ```elixir :ok = instance.clean_cache() ``` **Returns:** No return value. **Errors:** Returns `{:error, reason}` *** #### ExportInfo [Section titled “ExportInfo”](#exportinfo) An export statement extracted from source code. | Field | Type | Default | Description | | ------ | ------------ | -------- | -------------------------------------------------- | | `name` | `String.t()` | — | The exported name. | | `kind` | `ExportKind` | `:named` | The kind of export (named, default, or re-export). | | `span` | `Span` | — | Source span covering the export statement. | *** #### FileMetrics [Section titled “FileMetrics”](#filemetrics) Aggregate metrics for a source file. | Field | Type | Default | Description | | --------------- | ----------- | ------- | -------------------------------------------------------------- | | `total_lines` | `integer()` | — | Total number of lines (including blank and comment lines). | | `code_lines` | `integer()` | — | Number of lines containing non-blank, non-comment source code. | | `comment_lines` | `integer()` | — | Number of lines that are entirely comments. | | `blank_lines` | `integer()` | — | Number of blank (whitespace-only) lines. | | `total_bytes` | `integer()` | — | Total byte length of the source file. | | `node_count` | `integer()` | — | Total number of nodes in the syntax tree. | | `error_count` | `integer()` | — | Number of error nodes in the syntax tree (parse errors). | | `max_depth` | `integer()` | — | Maximum nesting depth reached in the syntax tree. | *** #### ImportInfo [Section titled “ImportInfo”](#importinfo) An import statement extracted from source code. | Field | Type | Default | Description | | ------------- | ------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `source` | `String.t()` | — | The module or path being imported from. | | `items` | `list(String.t())` | `[]` | Specific names imported from the source module. For `import a, b` / `from m import a, b`, every entry’s base name (never the alias). For a JavaScript/TypeScript named-imports clause (`import { a, b as c } from 'm'`), every specifier’s original name. Populated for Python and JavaScript/TypeScript only. Always empty for every other language this library recognises import statements for — Rust, Go, Java, Kotlin, and Elixir (`import`/`alias`/`require`/`use`) — and for a JS/TS namespace import (`import * as ns`) or default import (`import x from 'm'`), neither of which names individual items. | | `alias` | `String.t() \| nil` | `nil` | Alias assigned to the import (e.g., `import numpy as np`). Populated for Python’s single-name form (`import numpy as np`, `from m import a as b`) and JavaScript/TypeScript’s namespace form (`import * as ns from 'm'`) or a named-imports clause naming exactly one specifier (`import { a as b } from 'm'`). `nil` for Rust, Go, Java, Kotlin, and Elixir (which has its own `as:` alias option on `alias` directives, not yet extracted here) — and for a Python statement that aliases several names at once (`import os, sys as s`), where there is no single alias to report for the statement as a whole, so only `items` is populated for it. | | `is_wildcard` | `boolean()` | — | Whether this is a wildcard import (e.g., `import *` or `use foo.*`). Detected from the syntax tree — a dedicated wildcard node (`wildcard_import` in Python, `use_wildcard` in Rust) or a bare `*` token outside of string-literal content — not by searching the import’s source text for a `*` character, so a glob in an import path string (`import a from './glob*.js'`) is not mistaken for one. | | `span` | `Span` | — | Source span covering the import statement. | *** #### Language [Section titled “Language”](#language) *** #### LanguageRegistry [Section titled “LanguageRegistry”](#languageregistry) Thread-safe registry of tree-sitter language parsers. Manages both statically compiled and dynamically loaded language grammars. Use `LanguageRegistry.new()` for the default registry, or access the global instance via the module-level convenience functions (`get_language`, `available_languages`, etc.). ##### Functions [Section titled “Functions”](#functions-2) ###### new() [Section titled “new()”](#new-1) Create a new registry populated with all statically compiled languages. When the `dynamic-loading` feature is enabled, the registry also knows about dynamically loadable grammars and will load them on demand. **Signature:** ```elixir def new() ``` **Example:** ```elixir {:ok, result} = LanguageRegistry.new() ``` **Returns:** `LanguageRegistry` ###### get\_language() [Section titled “get\_language()”](#get_language-1) Get a tree-sitter `Language` by name. Resolves aliases (e.g., `"shell"` -> `"bash"`, `"makefile"` -> `"make"`), then looks up the language in the static table. When the `dynamic-loading` feature is enabled, falls back to loading a shared library on demand. **Errors:** Returns `Error.LanguageNotFound` if the name (after alias resolution) does not match any known grammar. **Signature:** ```elixir def get_language(obj, name) ``` **Example:** ```elixir {:ok, result} = instance.get_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------ | -------- | ----------- | | `name` | `String.t()` | Yes | The name | **Returns:** `Language` **Errors:** Returns `{:error, reason}` ###### available\_languages() [Section titled “available\_languages()”](#available_languages-1) List all available language names, sorted and deduplicated. Includes statically compiled languages, dynamically loadable languages (if the `dynamic-loading` feature is enabled), and all configured aliases. **Signature:** ```elixir def available_languages(obj) ``` **Example:** ```elixir {:ok, result} = instance.available_languages() ``` **Returns:** `list(String.t())` ###### has\_parser() [Section titled “has\_parser()”](#has_parser) Check whether this language can be parsed right now, without downloading. Resolves aliases, then answers from exactly the lookup `get_language` performs: the statically compiled table, the already-loaded dynamic grammars, and the parser shared libraries present in the primary and extra (download-cache) library directories. It never performs network I/O. A previous implementation consulted only the statically compiled table. That table is empty in every build that does not set `TSLP_LANGUAGES`, so the function answered `false` for languages this registry parses perfectly well. Contrast `has_language`, which is also `true` for a grammar that is merely *known to the manifest* and would have to be downloaded first. The pair distinguishes “we can parse it offline, now” from “we recognise the name”. The first `true` answer for a dynamic grammar loads its shared library: loading is the only way to know the grammar is usable, since a truncated or wrong-architecture library exists on disk but cannot parse. Loads are cached process-wide, so repeat calls are cheap. **Signature:** ```elixir def has_parser(obj, name) ``` **Example:** ```elixir {:ok, result} = instance.has_parser("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------ | -------- | ----------- | | `name` | `String.t()` | Yes | The name | **Returns:** `boolean()` ###### has\_language() [Section titled “has\_language()”](#has_language-1) Check whether a language is available by name or alias. Returns `true` if the language can be loaded, either from the static table or from a dynamic library on disk. Every branch is one more way to answer `true`, so they are ordered cheapest-first and the filesystem is only consulted once every in-memory source has said no. Probing the loaded-grammar map and the manifest ahead of the `stat` calls is what keeps this off the syscall path for the languages a process actually uses. **Signature:** ```elixir def has_language(obj, name) ``` **Example:** ```elixir {:ok, result} = instance.has_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------ | -------- | ----------- | | `name` | `String.t()` | Yes | The name | **Returns:** `boolean()` ###### language\_count() [Section titled “language\_count()”](#language_count-1) Return the total number of available languages (including aliases). Counts the same set `available_languages` lists, without materialising or sorting it. **Signature:** ```elixir def language_count(obj) ``` **Example:** ```elixir {:ok, result} = instance.language_count() ``` **Returns:** `integer()` ###### process() [Section titled “process()”](#process-1) Parse source code and extract file intelligence based on config in a single pass. **Errors:** Returns `Error.InvalidRange` if the config is invalid (see `ProcessConfig.validate`) or if the source exceeds the configured `max_source_bytes`; `Error.LanguageNotFound` if the language is unknown; or `Error.ParseFailed` if parsing produces no tree. **Signature:** ```elixir def process(obj, source, config) ``` **Example:** ```elixir {:ok, result} = instance.process("value", %{}) ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `String.t()` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Returns `{:error, reason}` *** #### Node [Section titled “Node”](#node) A single syntax node within a `Tree`. Nodes hold a strong reference to their parent tree so they remain valid regardless of how the tree is moved or stored at the FFI boundary. ##### Functions [Section titled “Functions”](#functions-3) ###### kind() [Section titled “kind()”](#kind) Return the node’s kind name (e.g. `"function_definition"`). **Signature:** ```elixir def kind(obj) ``` **Example:** ```elixir {:ok, result} = instance.kind() ``` **Returns:** `String.t()` ###### kind\_id() [Section titled “kind\_id()”](#kind_id) Return the node’s numeric kind ID. Tree-sitter assigns a stable `u16` ID to every node kind in a grammar (e.g. `"function_definition" → 42`). Comparing `kind_id()` is cheaper than comparing the string `kind()` in tight AST loops. **Signature:** ```elixir def kind_id(obj) ``` **Example:** ```elixir {:ok, result} = instance.kind_id() ``` **Returns:** `integer()` ###### start\_byte() [Section titled “start\_byte()”](#start_byte) Return the inclusive start byte offset of this node. **Signature:** ```elixir def start_byte(obj) ``` **Example:** ```elixir {:ok, result} = instance.start_byte() ``` **Returns:** `integer()` ###### end\_byte() [Section titled “end\_byte()”](#end_byte) Return the exclusive end byte offset of this node. **Signature:** ```elixir def end_byte(obj) ``` **Example:** ```elixir {:ok, result} = instance.end_byte() ``` **Returns:** `integer()` ###### byte\_range() [Section titled “byte\_range()”](#byte_range) Return the node’s byte range as a `ByteRange`. Callers should slice their own source bytes — this is a zero-copy text accessor. **Signature:** ```elixir def byte_range(obj) ``` **Example:** ```elixir {:ok, result} = instance.byte_range() ``` **Returns:** `ByteRange` ###### start\_position() [Section titled “start\_position()”](#start_position) Return the start `Point` (row, column). **Signature:** ```elixir def start_position(obj) ``` **Example:** ```elixir {:ok, result} = instance.start_position() ``` **Returns:** `Point` ###### end\_position() [Section titled “end\_position()”](#end_position) Return the end `Point` (row, column). **Signature:** ```elixir def end_position(obj) ``` **Example:** ```elixir {:ok, result} = instance.end_position() ``` **Returns:** `Point` ###### is\_named() [Section titled “is\_named()”](#is_named) True when this node is named (not punctuation/whitespace). **Signature:** ```elixir def is_named(obj) ``` **Example:** ```elixir {:ok, result} = instance.is_named() ``` **Returns:** `boolean()` ###### is\_error() [Section titled “is\_error()”](#is_error) True when this is an error node. **Signature:** ```elixir def is_error(obj) ``` **Example:** ```elixir {:ok, result} = instance.is_error() ``` **Returns:** `boolean()` ###### is\_missing() [Section titled “is\_missing()”](#is_missing) True when this is a missing-token node. **Signature:** ```elixir def is_missing(obj) ``` **Example:** ```elixir {:ok, result} = instance.is_missing() ``` **Returns:** `boolean()` ###### is\_extra() [Section titled “is\_extra()”](#is_extra) True when this is an “extra” node (e.g. a comment). **Signature:** ```elixir def is_extra(obj) ``` **Example:** ```elixir {:ok, result} = instance.is_extra() ``` **Returns:** `boolean()` ###### has\_error() [Section titled “has\_error()”](#has_error) True when this node or any descendant is an error. **Signature:** ```elixir def has_error(obj) ``` **Example:** ```elixir {:ok, result} = instance.has_error() ``` **Returns:** `boolean()` ###### parent() [Section titled “parent()”](#parent) Return this node’s parent, if any. **Signature:** ```elixir def parent(obj) ``` **Example:** ```elixir {:ok, result} = instance.parent() ``` **Returns:** `Node | nil` ###### child() [Section titled “child()”](#child) Return the i-th child of this node, if any. **Signature:** ```elixir def child(obj, index) ``` **Example:** ```elixir {:ok, result} = instance.child(42) ``` **Parameters:** | Name | Type | Required | Description | | ------- | ----------- | -------- | ----------- | | `index` | `integer()` | Yes | The index | **Returns:** `Node | nil` ###### child\_count() [Section titled “child\_count()”](#child_count) Total number of children (including unnamed). **Signature:** ```elixir def child_count(obj) ``` **Example:** ```elixir {:ok, result} = instance.child_count() ``` **Returns:** `integer()` ###### named\_child() [Section titled “named\_child()”](#named_child) Return the i-th named child of this node, if any. **Signature:** ```elixir def named_child(obj, index) ``` **Example:** ```elixir {:ok, result} = instance.named_child(42) ``` **Parameters:** | Name | Type | Required | Description | | ------- | ----------- | -------- | ----------- | | `index` | `integer()` | Yes | The index | **Returns:** `Node | nil` ###### named\_child\_count() [Section titled “named\_child\_count()”](#named_child_count) Number of named children of this node. **Signature:** ```elixir def named_child_count(obj) ``` **Example:** ```elixir {:ok, result} = instance.named_child_count() ``` **Returns:** `integer()` ###### child\_by\_field\_name() [Section titled “child\_by\_field\_name()”](#child_by_field_name) Look up a child by its grammar-defined field name. **Signature:** ```elixir def child_by_field_name(obj, name) ``` **Example:** ```elixir {:ok, result} = instance.child_by_field_name("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------ | -------- | ----------- | | `name` | `String.t()` | Yes | The name | **Returns:** `Node | nil` ###### to\_sexp() [Section titled “to\_sexp()”](#to_sexp) Return the S-expression form of this node’s subtree. **Signature:** ```elixir def to_sexp(obj) ``` **Example:** ```elixir {:ok, result} = instance.to_sexp() ``` **Returns:** `String.t()` ###### walk() [Section titled “walk()”](#walk) Return a `TreeCursor` positioned at this node. **Signature:** ```elixir def walk(obj) ``` **Example:** ```elixir {:ok, result} = instance.walk() ``` **Returns:** `TreeCursor` *** #### PackConfig [Section titled “PackConfig”](#packconfig) Configuration for the tree-sitter language pack. Controls cache directory and which languages to pre-download. Can be loaded from a TOML file, constructed programmatically, or passed as a dict/object from language bindings. | Field | Type | Default | Description | | ----------- | ------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cache_dir` | `String.t() \| nil` | `nil` | Override the BASE directory the parser cache lives under. This is a base, not the final library path: the crate appends `tree-sitter-language-pack/v{version}/libs` to it, exactly as it does to the platform default. So `cache_dir = "/tmp/my-parsers"` resolves to `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`. The suffix is not cosmetic. It keeps the whole cache tree — manifest, bundles and lock file included — inside a directory this library owns and versions. Earlier releases used this path verbatim, which put those files in the configured directory’s PARENT and let a cache built by one crate version be reused by another. Default base: the platform cache dir, e.g. `~/.cache` on Linux. | | `languages` | `list(String.t()) \| nil` | `[]` | Languages to pre-download on init. Each entry is a language name (e.g. `"python"`, `"rust"`). | | `groups` | `list(String.t()) \| nil` | `[]` | Language groups to pre-download. Group names come from the remote manifest, so the valid set is not fixed by this library; the published manifest currently defines only `"all"`. Call `manifest_groups` to enumerate them. An unknown name makes `init` fail. | *** #### Parser [Section titled “Parser”](#parser) A tree-sitter parser configured for one language at a time. ##### Functions [Section titled “Functions”](#functions-4) ###### new() [Section titled “new()”](#new-2) Construct a new parser with no language set and no parse limits. Call `Parser.set_language` before parsing. Limits are opt-in via `set_max_source_bytes` and `set_parse_timeout_ms`; both default to unbounded so that existing callers are unaffected. **Signature:** ```elixir def new() ``` **Example:** ```elixir {:ok, result} = Parser.new() ``` **Returns:** `Parser` ###### set\_max\_source\_bytes() [Section titled “set\_max\_source\_bytes()”](#set_max_source_bytes) Refuse to parse sources longer than `max_bytes`. `nil` (the default) means no limit. Over-limit input makes `parse` and `parse_bytes` return `nil` after emitting a `WARN`; input is never silently truncated. See `RECOMMENDED_MAX_SOURCE_BYTES`. **Signature:** ```elixir def set_max_source_bytes(obj, max_bytes) ``` **Example:** ```elixir :ok = instance.set_max_source_bytes(42) ``` **Parameters:** | Name | Type | Required | Description | | ----------- | ------------------ | -------- | ------------- | | `max_bytes` | `integer() \| nil` | No | The max bytes | **Returns:** No return value. ###### set\_parse\_timeout\_ms() [Section titled “set\_parse\_timeout\_ms()”](#set_parse_timeout_ms) Cancel a parse that exceeds `timeout_ms` milliseconds of wall clock. `nil` (the default) means no budget. Cancellation runs through tree-sitter’s parse progress callback, so it is granular to that callback’s interval rather than exact. See `RECOMMENDED_PARSE_TIMEOUT_MS`. **Signature:** ```elixir def set_parse_timeout_ms(obj, timeout_ms) ``` **Example:** ```elixir :ok = instance.set_parse_timeout_ms(42) ``` **Parameters:** | Name | Type | Required | Description | | ------------ | ------------------ | -------- | -------------- | | `timeout_ms` | `integer() \| nil` | No | The timeout ms | **Returns:** No return value. ###### set\_language() [Section titled “set\_language()”](#set_language) Configure the parser to use the language identified by name (e.g. `"python"`). Resolves the language through the global registry — auto-downloading if necessary, when the `download` feature is enabled. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language ABI is incompatible. **Signature:** ```elixir def set_language(obj, name) ``` **Example:** ```elixir :ok = instance.set_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------------ | -------- | ----------- | | `name` | `String.t()` | Yes | The name | **Returns:** No return value. **Errors:** Returns `{:error, reason}` ###### parse() [Section titled “parse()”](#parse) Parse a UTF-8 source string. Returns `nil` if no language is set, if the parse was cancelled by the configured timeout, or if the source exceeds the configured size limit. Each non-parse outcome is logged, so an empty result is never silent. ###### Concurrency [Section titled “Concurrency”](#concurrency) Parsing runs fully in parallel across threads for almost every language — no lock is taken. The exception is the small set of grammars whose external scanner keeps mutable process-global state (currently just `properties`): parses of that language are serialized against each other through an internal per-language lock, so that concurrent threads can’t corrupt shared scanner state. Every other language is unaffected by that lock and never waits on it. **Signature:** ```elixir def parse(obj, source) ``` **Example:** ```elixir {:ok, result} = instance.parse("value") ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ----------- | | `source` | `String.t()` | Yes | The source | **Returns:** `Tree | nil` ###### parse\_bytes() [Section titled “parse\_bytes()”](#parse_bytes) Parse a raw byte slice. Same outcomes as `parse`, including the concurrency behaviour documented there. **Signature:** ```elixir def parse_bytes(obj, source) ``` **Example:** ```elixir {:ok, result} = instance.parse_bytes(<<100, 97, 116, 97>>) ``` **Parameters:** | Name | Type | Required | Description | | -------- | ---------- | -------- | ----------- | | `source` | `binary()` | Yes | The source | **Returns:** `Tree | nil` ###### reset() [Section titled “reset()”](#reset) Reset internal state. The next call to `parse` will not be incremental. **Signature:** ```elixir def reset(obj) ``` **Example:** ```elixir :ok = instance.reset() ``` **Returns:** No return value. *** #### Point [Section titled “Point”](#point) A source position — row + column, zero-indexed. | Field | Type | Default | Description | | -------- | ----------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `row` | `integer()` | — | Zero-indexed row number. | | `column` | `integer()` | — | Zero-indexed column, counted in **bytes** from the start of the row. This is `tree_sitter.Point.column` verbatim, and tree-sitter defines it as a byte offset — not characters, and not UTF-16 code units. Measured on a row of the form `x = ''` where `` is a single 4-byte character (an emoji), the string node reports columns `4..10`, identical to its byte range; the character columns would be `4..7` and the UTF-16 columns `4..8`. Anything that builds LSP positions (UTF-16) or editor caret columns (characters) from this field is silently wrong on every row containing a non-ASCII byte, and must re-measure the row against the source text instead. Earlier releases documented this field as UTF-16 code units; that was never what the value contained. | *** #### ProcessConfig [Section titled “ProcessConfig”](#processconfig) Configuration for the `process()` function. Controls which analysis features are enabled and whether chunking is performed. | Field | Type | Default | Description | | ------------------ | ------------------ | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String.t()` | `""` | Language name (required). | | `structure` | `boolean()` | `true` | Extract structural items (functions, classes, etc.). Default: true. | | `imports` | `boolean()` | `true` | Extract import statements. Default: true. | | `exports` | `boolean()` | `true` | Extract export statements. Default: true. | | `comments` | `boolean()` | `false` | Extract comments. Default: false. | | `docstrings` | `boolean()` | `false` | Extract docstrings. Default: false. | | `symbols` | `boolean()` | `false` | Extract symbol definitions. Default: false. | | `diagnostics` | `boolean()` | `false` | Include parse diagnostics. Default: false. | | `chunk_max_size` | `integer() \| nil` | `nil` | Maximum chunk size in bytes. `nil` disables chunking. `Some(0)` is rejected by `ProcessConfig.validate` with `Error.InvalidRange`. A zero-sized chunk limit previously produced an empty chunk list and silently discarded the whole source; use `nil` to mean “do not chunk”. | | `data_extraction` | `boolean()` | `false` | Extract hierarchical key/value data tree from data-format files. Default: false. When `true`, `ProcessResult.data` is populated with a `DataNode` tree for supported languages: JSON, YAML, TOML, `.properties`, HCL/HOCON, INI, editorconfig, KDL, CUE, CSV, PSV, PO, nginx config, Caddy config, XML, and DTD. For languages outside this set the field is left as `nil`. | | `max_source_bytes` | `integer() \| nil` | `nil` | Reject source longer than this many bytes instead of parsing it. Default: `nil` (unbounded). Tree-sitter allocates and walks proportionally to input size, so an unbounded parse of attacker-supplied input is a denial-of-service vector. The default stays unbounded for backward compatibility; services handling untrusted input should opt in, e.g. with `RECOMMENDED_MAX_SOURCE_BYTES`. Exceeding the limit fails the call with `Error.InvalidRange` — the source is never silently truncated. | | `parse_timeout_ms` | `integer() \| nil` | `nil` | Wall-clock budget for the parse step, in milliseconds. Default: `nil` (no timeout). Enforced through tree-sitter’s parse progress callback, which the parser invokes periodically; cancellation is therefore granular to that callback interval rather than exact. A parse that exceeds the budget fails with `Error.ParseTimeout`. | *** #### ProcessResult [Section titled “ProcessResult”](#processresult) Complete analysis result from processing a source file. Contains metrics, structural analysis, imports/exports, comments, docstrings, symbols, diagnostics, and optionally chunked code segments. Fields are populated based on the `ProcessConfig` flags. | Field | Type | Default | Description | | ------------- | --------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String.t()` | — | The language name used to parse the source file. | | `metrics` | `FileMetrics` | — | File-level metrics (line counts, byte size, error count). | | `structure` | `list(StructureItem)` | `[]` | Top-level structural items (functions, classes, etc.). | | `imports` | `list(ImportInfo)` | `[]` | Import statements extracted from the source. | | `exports` | `list(ExportInfo)` | `[]` | Export statements extracted from the source. | | `comments` | `list(CommentInfo)` | `[]` | Comments extracted from the source. | | `docstrings` | `list(DocstringInfo)` | `[]` | Docstrings extracted from the source. | | `symbols` | `list(SymbolInfo)` | `[]` | Symbol definitions (variables, types, functions) extracted from the source. | | `diagnostics` | `list(Diagnostic)` | `[]` | Parse diagnostics (syntax errors, missing nodes) from tree-sitter. | | `chunks` | `list(CodeChunk)` | `[]` | Syntax-aware code chunks produced when chunking is enabled. | | `data` | `DataNode \| nil` | `nil` | Hierarchical data tree extracted when `config.data_extraction` is `true`. Populated for supported data-format languages (JSON, YAML, TOML, properties, HCL, INI, XML, CSV, and more). `nil` when `data_extraction` is `false` (the default) or when the language is not a recognised data format. See `DataNode` for the shape of the returned tree. | *** #### Span [Section titled “Span”](#span) Byte and line/column range in source code. Represents both byte offsets (for slicing) and human-readable line/column positions (for display and diagnostics). | Field | Type | Default | Description | | -------------- | ----------- | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `start_byte` | `integer()` | — | Inclusive start byte offset in the source. | | `end_byte` | `integer()` | — | Exclusive end byte offset in the source. | | `start_line` | `integer()` | — | Zero-indexed line number of the span’s start. | | `start_column` | `integer()` | — | Zero-indexed column of the span’s start, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | | `end_line` | `integer()` | — | Zero-indexed line number of the span’s end. | | `end_column` | `integer()` | — | Zero-indexed column of the span’s end, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | *** #### StructureItem [Section titled “StructureItem”](#structureitem) A structural item (function, class, struct, etc.) in source code. | Field | Type | Default | Description | | ------------- | --------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `kind` | `StructureKind` | `:function` | The kind of structural item. | | `name` | `String.t() \| nil` | `nil` | The declared name of the item, if present. | | `visibility` | `String.t() \| nil` | `nil` | Visibility modifier (e.g., `"pub"`, `"public"`, `"private"`). | | `span` | `Span` | — | Source span covering the entire item declaration. | | `children` | `list(StructureItem)` | `[]` | Nested structural items (e.g., methods within a class). | | `decorators` | `list(String.t())` | `[]` | Decorator or attribute names applied to the item. **Reserved: not yet populated.** Always empty, for every language. Recognising a decorator requires per-language grammar knowledge (a Python `decorated_definition` wrapper, Java/C# annotations, Rust attributes each have a different shape), which no extractor here implements yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | | `doc_comment` | `String.t() \| nil` | `nil` | Documentation comment attached to the item, if any. The text of the comment (or run of comments) immediately preceding the item, with no blank line in between, when that comment is classified as a doc comment. Multiple adjacent single-line doc comments (Rust `///`) are joined with `\n` in source order. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`). `nil` for every other language, and for a preceding comment that is not in doc-comment form (a plain `#` comment in Python, Ruby, or Elixir) — Python’s docstring convention is captured separately, as `DocstringInfo`, not through this field. | | `signature` | `String.t() \| nil` | `nil` | Full signature text of the item (e.g., function parameters and return type). The item’s own source text from its start up to the start of its body (see `StructureItem.body_span`), trimmed of trailing whitespace — for example `fn add(a: i32, b: i32) -> i32` for a Rust function whose body is `{ a + b }`. `nil` only when that text is empty, which does not happen for any item `StructureKind` currently reports. Populated for every language and kind this library extracts structure for, since it is derived from `body_span`’s boundary rather than per-language syntax. | | `body_span` | `Span \| nil` | `nil` | Source span covering only the body of the item, if distinct from the declaration. | *** #### SymbolInfo [Section titled “SymbolInfo”](#symbolinfo) A symbol (variable, function, type, etc.) extracted from source code. | Field | Type | Default | Description | | ----------------- | ------------------- | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `String.t()` | — | The name of the symbol. | | `kind` | `SymbolKind` | `:variable` | The kind of symbol (variable, function, class, etc.). | | `span` | `Span` | — | Source span covering the symbol definition. | | `type_annotation` | `String.t() \| nil` | `nil` | Explicit type annotation, if present in the source. | | `doc` | `String.t() \| nil` | `nil` | Documentation comment immediately preceding this symbol, resolved by the same walk `StructureItem.doc_comment` uses (see `doc_comment_at`) — never hard-coded `nil`. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`) — the languages whose comment classification recognizes a doc-kind comment. `nil` for every other language (e.g. Python, Go, Ruby, which have no doc-kind comment classification), and also `nil` when a symbol in a supported language simply has no doc comment immediately above it. | *** #### Tree [Section titled “Tree”](#tree) A parsed syntax tree. Cheap to clone (refcount bump). ##### Functions [Section titled “Functions”](#functions-5) ###### root\_node() [Section titled “root\_node()”](#root_node) Return the root `Node` of this tree. **Signature:** ```elixir def root_node(obj) ``` **Example:** ```elixir {:ok, result} = instance.root_node() ``` **Returns:** `Node` ###### walk() [Section titled “walk()”](#walk-1) Return a `TreeCursor` positioned at the root. **Signature:** ```elixir def walk(obj) ``` **Example:** ```elixir {:ok, result} = instance.walk() ``` **Returns:** `TreeCursor` *** #### TreeCursor [Section titled “TreeCursor”](#treecursor) A cursor for traversing a `Tree`. ##### Functions [Section titled “Functions”](#functions-6) ###### node() [Section titled “node()”](#node-1) Return the `Node` at the cursor’s current position. **Signature:** ```elixir def node(obj) ``` **Example:** ```elixir {:ok, result} = instance.node() ``` **Returns:** `Node` ###### goto\_first\_child() [Section titled “goto\_first\_child()”](#goto_first_child) Move the cursor to the first child of the current node. Returns `true` if a child existed. **Signature:** ```elixir def goto_first_child(obj) ``` **Example:** ```elixir {:ok, result} = instance.goto_first_child() ``` **Returns:** `boolean()` ###### goto\_parent() [Section titled “goto\_parent()”](#goto_parent) Move the cursor to the parent of the current node. Returns `true` if a parent existed. **Signature:** ```elixir def goto_parent(obj) ``` **Example:** ```elixir {:ok, result} = instance.goto_parent() ``` **Returns:** `boolean()` ###### goto\_next\_sibling() [Section titled “goto\_next\_sibling()”](#goto_next_sibling) Move the cursor to the next sibling of the current node. Returns `true` if a sibling existed. **Signature:** ```elixir def goto_next_sibling(obj) ``` **Example:** ```elixir {:ok, result} = instance.goto_next_sibling() ``` **Returns:** `boolean()` ###### field\_name() [Section titled “field\_name()”](#field_name) Return the field name for the current node, if any. **Signature:** ```elixir def field_name(obj) ``` **Example:** ```elixir {:ok, result} = instance.field_name() ``` **Returns:** `String.t() | nil` *** ### Enums [Section titled “Enums”](#enums) #### DataNodeKind [Section titled “DataNodeKind”](#datanodekind) The kind of a data node extracted from a data-format file. Classifies each node in the hierarchical `DataNode` tree returned when `data_extraction` is enabled on `ProcessConfig`. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract) Unit variants serialize as a bare string (`"KeyValue"`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | -------------------------------------------------------------------------------------------------------------------- | | `key_value` | A key/value pair or mapping (json/toml/properties/yaml/hcl/cue/kdl pair, or a wrapper “object”/“mapping” container). | | `element` | An XML element with a tag name in `key` and attributes in `attributes`. | | `sequence` | A positional sequence item (JSON array element, YAML block sequence item, CSV/PSV row or cell). | *** #### StructureKind [Section titled “StructureKind”](#structurekind) The kind of structural item found in source code. Categorizes top-level and nested declarations such as functions, classes, structs, enums, traits, and more. Use `Other` for language-specific constructs that do not fit a standard category. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-1) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | -------------------------------------------------------------------------------------------------- | | `function` | A free-standing or associated function. | | `method` | A method defined inside a class, struct, trait, or impl block. | | `class` | A class definition. | | `struct` | A struct definition. | | `interface` | An interface or protocol definition. | | `enum` | An enum definition. | | `module` | A module or package declaration. | | `trait` | A trait definition. | | `impl` | An impl block (Rust) or similar implementation block. | | `namespace` | A namespace declaration. | | `other` | A language-specific construct that does not fit any standard category. — Fields: `0`: `String.t()` | *** #### CommentKind [Section titled “CommentKind”](#commentkind) The kind of a comment found in source code. Distinguishes between single-line comments, block (multi-line) comments, and documentation comments. | Value | Description | | ------- | --------------------------------------------------------------------- | | `line` | A single-line comment (e.g., `// ...` or `# ...`). | | `block` | A block or multi-line comment using slash-star delimiters. | | `doc` | A documentation comment such as `/// ...` or slash-double-star block. | *** #### DocstringFormat [Section titled “DocstringFormat”](#docstringformat) The format of a docstring extracted from source code. Identifies the docstring convention used, which varies by language (e.g., Python triple-quoted strings, JSDoc, Rustdoc `///` comments). ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-2) Unit variants serialize as a bare string (`"JSDoc"`); the `Other` variant serializes as a single-keyed object (`{"Other": "rst"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | --------------------- | ------------------------------------------------------------------------------------------------------ | | `python_triple_quote` | Python triple-quoted string docstring (`"""..."""`). | | `js_doc` | JavaScript/TypeScript JSDoc block comment (opens with two stars, closes with star-slash). | | `rustdoc` | Rust `///` or `//!` doc comment. | | `go_doc` | Go doc comment (a comment block immediately preceding a declaration). | | `java_doc` | Java Javadoc block comment (opens with two stars, closes with star-slash). | | `other` | A language-specific docstring format not covered by the standard variants. — Fields: `0`: `String.t()` | *** #### ExportKind [Section titled “ExportKind”](#exportkind) The kind of an export statement found in source code. Covers named exports, default exports, and re-exports from other modules. | Value | Description | | ----------- | -------------------------------------------------------------------- | | `named` | A named export (e.g., `export { foo }`). | | `default` | A default export (e.g., `export default foo`). | | `re_export` | A re-export from another module (e.g., `export { foo } from 'bar'`). | *** #### SymbolKind [Section titled “SymbolKind”](#symbolkind) The kind of a symbol definition found in source code. Categorizes symbol definitions such as variables, constants, functions, classes, types, interfaces, enums, and modules. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-3) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | ------------------------------------------------------------------------------- | | `variable` | A variable binding. | | `constant` | A constant (immutable binding). | | `function` | A function definition. | | `class` | A class definition. | | `type` | A type alias or typedef. | | `interface` | An interface definition. | | `enum` | An enum definition. | | `module` | A module declaration. | | `other` | A symbol kind not covered by the standard variants. — Fields: `0`: `String.t()` | *** #### DiagnosticSeverity [Section titled “DiagnosticSeverity”](#diagnosticseverity) Severity level of a diagnostic produced during parsing. Used to classify parse errors, warnings, and informational messages found in the syntax tree. | Value | Description | | --------- | --------------------------------------------------------------- | | `error` | A parse error (e.g., an `ERROR` or `MISSING` node in the tree). | | `warning` | A warning-level diagnostic. | | `info` | An informational diagnostic. | *** ### Errors [Section titled “Errors”](#errors) #### Error [Section titled “Error”](#error) Errors that can occur when using the tree-sitter language pack. Covers language lookup failures, parse errors, query errors, and I/O issues. Feature-gated variants are included when `config`, `download`, or related features are enabled. ##### Matching on `Error` [Section titled “Matching on Error”](#matching-on-error) The set of variants is not stable: new failure modes are added in minor releases, and `Io`, `Json`, and `Toml` exist only under certain feature combinations, so the variant set a downstream crate sees depends on which features it enables. Downstream `match`es must therefore carry a `_` arm; `#[non_exhaustive]` makes the compiler enforce that instead of letting a feature change silently break a build. ##### C ABI error codes [Section titled “C ABI error codes”](#c-abi-error-codes) Each variant alef can see carries an explicit `alef(error_code = N)` allocation that becomes a member of the generated `AlefFfiErrorCode` C enum. These numbers are a public ABI contract: **an allocated number is never reused after its variant is removed**, and a variant’s number never changes, because C callers compare against the value, not the name. New variants take the next free number. 0-4 are reserved by alef, so allocation starts at 100. An unannotated variant is emitted as the unknown code rather than as itself, which silently flattens the taxonomy — annotate every new variant. | Variant | Description | | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language_not_found` | The requested language name (or alias) was not found in the registry. | | `dynamic_load` | A dynamic shared library could not be loaded at runtime. | | `null_language_pointer` | The tree-sitter language function returned a null pointer for the given language name. | | `parser_setup` | The language could not be applied to the parser (e.g., ABI version mismatch). | | `lock_poisoned` | An internal `RwLock` or `Mutex` was poisoned by a previous panic. | | `config` | A configuration file or value was invalid or could not be applied. | | `parse_failed` | The tree-sitter parser returned no tree for the given source input. | | `parse_timeout` | The parse was cancelled because it exceeded its configured wall-clock budget. Raised only when a budget is configured — see `ProcessConfig.parse_timeout_ms`, which defaults to `nil`. | | `query_error` | A tree-sitter query could not be compiled or executed. | | `invalid_range` | A byte range was invalid (e.g., end before start, or out of bounds). | | `download` | A parser download from GitHub releases failed. | | `checksum_mismatch` | The downloaded file’s SHA-256 digest did not match the manifest’s expected value. | | `cache_lock` | The cross-process download cache lock file could not be acquired or created. | *** # Go API Reference ## Go API Reference v1.16.1 [Section titled “Go API Reference v1.16.1”](#go-api-reference-v1161) ### Functions [Section titled “Functions”](#functions) #### DetectLanguageFromExtension() [Section titled “DetectLanguageFromExtension()”](#detectlanguagefromextension) Detect language name from a file extension (without leading dot). Returns `nil` for unrecognized extensions. The match is case-insensitive. **Signature:** ```go func DetectLanguageFromExtension(ext string) *string ``` **Example:** ```go result := DetectLanguageFromExtension("value") ``` **Parameters:** | Name | Type | Required | Description | | ----- | -------- | -------- | ----------- | | `Ext` | `string` | Yes | The ext | **Returns:** `*string` *** #### DetectLanguageFromPath() [Section titled “DetectLanguageFromPath()”](#detectlanguagefrompath) Detect language name from a file path. Extracts the file extension and looks it up. Returns `nil` if the path has no extension or the extension is not recognized. **Signature:** ```go func DetectLanguageFromPath(path string) *string ``` **Example:** ```go result := DetectLanguageFromPath("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `Path` | `string` | Yes | Path to the file | **Returns:** `*string` *** #### DetectLanguageFromContent() [Section titled “DetectLanguageFromContent()”](#detectlanguagefromcontent) Detect language name from file content using the shebang line (`#!`). Inspects only the first line of `content`. If it begins with `#!`, the interpreter name is extracted and mapped to a language name. Handles common patterns: * `#!/usr/bin/env python3` → `"python"` * `#!/bin/bash` → `"bash"` * `#!/usr/bin/env node` → `"javascript"` The `-S` flag accepted by some `env` implementations is skipped automatically. Version suffixes (e.g. `python3.11`, `ruby3.2`) are stripped before matching. A leading UTF-8 BOM (`U+FEFF`) is skipped before the `#!` check, so a BOM-prefixed script is still detected by its shebang. Returns `nil` when content does not start with `#!` (after stripping a leading BOM), the shebang is malformed, or the interpreter is not recognised. **Signature:** ```go func DetectLanguageFromContent(content string) *string ``` **Example:** ```go result := DetectLanguageFromContent("value") ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ---------------------- | | `Content` | `string` | Yes | The content to process | **Returns:** `*string` *** #### GetHighlightsQuery() [Section titled “GetHighlightsQuery()”](#gethighlightsquery) Get the highlights query for a language, if bundled. Returns the contents of `highlights.scm` as a static string, or `nil` if no highlights query is bundled for this language. **Signature:** ```go func GetHighlightsQuery(language string) *string ``` **Example:** ```go result := GetHighlightsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `Language` | `string` | Yes | The language | **Returns:** `*string` *** #### GetInjectionsQuery() [Section titled “GetInjectionsQuery()”](#getinjectionsquery) Get the injections query for a language, if bundled. Returns the contents of `injections.scm` as a static string, or `nil` if no injections query is bundled for this language. **Signature:** ```go func GetInjectionsQuery(language string) *string ``` **Example:** ```go result := GetInjectionsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `Language` | `string` | Yes | The language | **Returns:** `*string` *** #### GetLocalsQuery() [Section titled “GetLocalsQuery()”](#getlocalsquery) Get the locals query for a language, if bundled. Returns the contents of `locals.scm` as a static string, or `nil` if no locals query is bundled for this language. **Signature:** ```go func GetLocalsQuery(language string) *string ``` **Example:** ```go result := GetLocalsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `Language` | `string` | Yes | The language | **Returns:** `*string` *** #### GetTagsQuery() [Section titled “GetTagsQuery()”](#gettagsquery) Get the tags query for a language, if bundled. Returns the contents of `tags.scm` as a static string, or `nil` if no tags query is bundled for this language. **Signature:** ```go func GetTagsQuery(language string) *string ``` **Example:** ```go result := GetTagsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `Language` | `string` | Yes | The language | **Returns:** `*string` *** #### GetIndentsQuery() [Section titled “GetIndentsQuery()”](#getindentsquery) Get the indents query for a language, if bundled. Returns the contents of `indents.scm` (used for auto-indentation) as a static string, or `nil` if no indents query is bundled for this language. **Signature:** ```go func GetIndentsQuery(language string) *string ``` **Example:** ```go result := GetIndentsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `Language` | `string` | Yes | The language | **Returns:** `*string` *** #### GetFoldsQuery() [Section titled “GetFoldsQuery()”](#getfoldsquery) Get the folds query for a language, if bundled. Returns the contents of `folds.scm` (used for code folding) as a static string, or `nil` if no folds query is bundled for this language. **Signature:** ```go func GetFoldsQuery(language string) *string ``` **Example:** ```go result := GetFoldsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `Language` | `string` | Yes | The language | **Returns:** `*string` *** #### GetLanguage() [Section titled “GetLanguage()”](#getlanguage) Get a tree-sitter `Language` by name using the global registry. Resolves language aliases (e.g., `"shell"` maps to `"bash"`). When the `download` feature is enabled (default), automatically downloads the parser from GitHub releases if not found locally. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.Download` if auto-download fails. **Signature:** ```go func GetLanguage(name string) (*Language, error) ``` **Example:** ```go result, err := GetLanguage("value") if err != nil { return err } ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** `Language` **Errors:** Returns `error`. *** #### GetParser() [Section titled “GetParser()”](#getparser) Get a `Parser` pre-configured for the given language. This is a convenience function that calls `get_language` and configures a new parser in one step. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language cannot be applied to the parser. **Signature:** ```go func GetParser(name string) (*Parser, error) ``` **Example:** ```go result, err := GetParser("value") if err != nil { return err } ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** `Parser` **Errors:** Returns `error`. *** #### DetectLanguage() [Section titled “DetectLanguage()”](#detectlanguage) Detect language name from a file path or extension. This compatibility alias matches the pre-Alef Python binding API. **Signature:** ```go func DetectLanguage(path string) *string ``` **Example:** ```go result := DetectLanguage("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `Path` | `string` | Yes | Path to the file | **Returns:** `*string` *** #### AvailableLanguages() [Section titled “AvailableLanguages()”](#availablelanguages) List all available language names (sorted, deduplicated, includes aliases). Returns names of both statically compiled and dynamically loadable languages, plus any configured aliases. **Signature:** ```go func AvailableLanguages() []string ``` **Example:** ```go result := AvailableLanguages() ``` **Returns:** `[]string` *** #### HasLanguage() [Section titled “HasLanguage()”](#haslanguage) Check if a language is available by name or alias. Returns `true` if the language can be loaded (statically compiled, dynamically available, or a known alias for one of these). **Signature:** ```go func HasLanguage(name string) bool ``` **Example:** ```go result := HasLanguage("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** `bool` *** #### LanguageCount() [Section titled “LanguageCount()”](#languagecount) Return the number of available languages. Includes statically compiled languages, dynamically loadable languages, and aliases. **Signature:** ```go func LanguageCount() uint ``` **Example:** ```go result := LanguageCount() ``` **Returns:** `uint` *** #### Process() [Section titled “Process()”](#process) Process source code and extract file intelligence using the global registry. Parses the source with tree-sitter and extracts metrics, structure, imports, exports, comments, docstrings, symbols, diagnostics, and/or chunks based on the flags set in `ProcessConfig`. **Errors:** Returns `Error.InvalidRange` if the config carries a zero-valued limit or the source exceeds `ProcessConfig.max_source_bytes`, `Error.ParseTimeout` if the parse exceeds `ProcessConfig.parse_timeout_ms`, `Error.LanguageNotFound` if the language is unknown, or `Error.ParseFailed` if parsing yields no tree. **Signature:** ```go func Process(source string, config ProcessConfig) (*ProcessResult, error) ``` **Example:** ```go result, err := Process("value", ProcessConfig{}) if err != nil { return err } ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `Source` | `string` | Yes | The source | | `Config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Returns `error`. *** #### Init() [Section titled “Init()”](#init) Initialize the language pack with the given configuration. Applies any custom cache directory, then downloads all languages and groups specified in the config. This is the recommended entry point when you want to pre-warm the cache before use. **Errors:** Returns an error if configuration cannot be applied or if downloads fail. **Signature:** ```go func Init(config PackConfig) error ``` **Example:** ```go if err := Init(PackConfig{}); err != nil { return err } ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `Config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Returns `error`. *** #### Configure() [Section titled “Configure()”](#configure) Apply download configuration without downloading anything. Use this to set a custom cache directory before the first call to `get_language` or any download function. Changing the cache dir after languages have been registered has no effect on already-loaded languages. `PackConfig.cache_dir` is a BASE directory, not the final libs path: this crate appends `tree-sitter-language-pack/v{version}/libs` to it, the same suffix applied to the platform default cache directory. In the example below, files actually land under `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`, never directly in `/tmp/my-parsers/`. Call `cache_dir` to read back the resolved, fully-suffixed path. **Errors:** Returns an error if the lock cannot be acquired. **Signature:** ```go func Configure(config PackConfig) error ``` **Example:** ```go if err := Configure(PackConfig{}); err != nil { return err } ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `Config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Returns `error`. *** #### Download() [Section titled “Download()”](#download) Download specific languages to the local cache. Returns the number of distinct languages available after the call. Already compiled or cached languages are included in the count. Aliases are resolved before counting, so `["shell", "bash"]` names one language and returns 1. **Errors:** Returns an error if any language is not available in the manifest or if the download fails. **Signature:** ```go func Download(names []string) (uint, error) ``` **Example:** ```go result, err := Download(nil) if err != nil { return err } ``` **Parameters:** | Name | Type | Required | Description | | ------- | ------------ | -------- | ----------- | | `Names` | `\[\]string` | Yes | The names | **Returns:** `uint` **Errors:** Returns `error`. *** #### Prefetch() [Section titled “Prefetch()”](#prefetch) Prefetch grammars: download any not already loadable from disk, then load every requested language into the process registry so a subsequent hot loop only parses. Unlike `download()`, this does not trust in-memory availability — it downloads whenever a grammar is not actually loadable from disk (fixing the case where a known-but-not-downloaded grammar is reported present), then resolves and caches every requested language. Call it once, up front, before a parallel workload. **Errors:** Returns `Error.Download` if a required grammar cannot be fetched, or `Error.LanguageNotFound` if a requested name is unknown. **Signature:** ```go func Prefetch(languages []string) error ``` **Example:** ```go if err := Prefetch(nil); err != nil { return err } ``` **Parameters:** | Name | Type | Required | Description | | ----------- | ------------ | -------- | ------------- | | `Languages` | `\[\]string` | Yes | The languages | **Returns:** No return value. **Errors:** Returns `error`. *** #### DownloadAll() [Section titled “DownloadAll()”](#downloadall) Download all available languages from the remote manifest. Downloads the platform bundle and extracts every library it contains. Languages that appear in the manifest but are absent from the bundle (e.g. grammars that failed to compile at release time) are silently skipped — they are not treated as an error. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns an error if the manifest cannot be fetched or the bundle download fails. **Signature:** ```go func DownloadAll() (uint, error) ``` **Example:** ```go result, err := DownloadAll() if err != nil { return err } ``` **Returns:** `uint` **Errors:** Returns `error`. *** #### DownloadGroup() [Section titled “DownloadGroup()”](#downloadgroup) Download every language in a named group. Groups are defined by the remote manifest, not by this library, and let you ensure a curated set of related grammars in one call instead of listing each name to `download()`. Already-cached languages are skipped. Call `manifest_groups` to discover the group names the manifest actually defines. The published manifest currently defines a single group, `"all"`; earlier revisions of this documentation advertised `"web"`, `"data"`, and `"systems"`, which the manifest has never contained, so every call following that example failed. Do not hardcode a group name without checking. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns `Error.Download` if the manifest cannot be fetched, if the group is unknown — the message lists the groups the manifest defines — or if any constituent language fails to download. **Signature:** ```go func DownloadGroup(name string) (uint, error) ``` **Example:** ```go result, err := DownloadGroup("value") if err != nil { return err } ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** `uint` **Errors:** Returns `error`. *** #### ManifestLanguages() [Section titled “ManifestLanguages()”](#manifestlanguages) Return all language names available in the remote manifest (371). Fetches (and caches) the remote manifest to discover the full list of downloadable languages. Use `downloaded_languages` to list what is already cached locally. **Errors:** Returns an error if the manifest cannot be fetched. **Signature:** ```go func ManifestLanguages() ([]string, error) ``` **Example:** ```go result, err := ManifestLanguages() if err != nil { return err } ``` **Returns:** `[]string` **Errors:** Returns `error`. *** #### ManifestGroups() [Section titled “ManifestGroups()”](#manifestgroups) Return the names of every language group the remote manifest defines, sorted. Group names are manifest data, not a compile-time constant of this library, so this is the only reliable way to learn what `download_group` and `PackConfig.groups` accept. The published manifest currently defines just `"all"`. **Errors:** Returns `Error.Download` if the manifest cannot be fetched. **Signature:** ```go func ManifestGroups() ([]string, error) ``` **Example:** ```go result, err := ManifestGroups() if err != nil { return err } ``` **Returns:** `[]string` **Errors:** Returns `error`. *** #### DownloadedLanguages() [Section titled “DownloadedLanguages()”](#downloadedlanguages) Return languages that are already downloaded and cached locally. Does not perform any network requests. Returns an empty list if the cache directory does not exist or cannot be read. **Signature:** ```go func DownloadedLanguages() []string ``` **Example:** ```go result := DownloadedLanguages() ``` **Returns:** `[]string` *** #### CleanCache() [Section titled “CleanCache()”](#cleancache) Delete all cached parser shared libraries. Resets the cache registration so the next call to `get_language` or a download function will re-register the (now empty) cache directory. **Errors:** Returns an error if the cache directory cannot be removed. **Signature:** ```go func CleanCache() error ``` **Example:** ```go if err := CleanCache(); err != nil { return err } ``` **Returns:** No return value. **Errors:** Returns `error`. *** #### CacheDir() [Section titled “CacheDir()”](#cachedir) Return the effective cache directory path. This is `{base}/tree-sitter-language-pack/v{version}/libs/`, where `{base}` is either the custom BASE directory set via `configure` / `init` (`PackConfig.cache_dir`) or the platform default cache directory — both are suffixed identically, so a custom `cache_dir` is never used as the final libs path. The default resolves to `~/.cache/tree-sitter-language-pack/v{version}/libs/` on a typical Unix system. **Errors:** Returns an error if no cache directory can be resolved: `version` is somehow invalid, or (with no custom `cache_dir` configured) the platform reports none and `TREE_SITTER_LANGUAGE_PACK_CACHE_DIR` is unset. This crate no longer falls back to the temporary directory for the latter case — see #101 H2. **Signature:** ```go func CacheDir() (string, error) ``` **Example:** ```go result, err := CacheDir() if err != nil { return err } ``` **Returns:** `string` **Errors:** Returns `error`. *** ### Types [Section titled “Types”](#types) #### ByteRange [Section titled “ByteRange”](#byterange) A byte range — start (inclusive) to end (exclusive). | Field | Type | Default | Description | | ------- | ------ | ------- | ---------------------------- | | `Start` | `uint` | — | Inclusive start byte offset. | | `End` | `uint` | — | Exclusive end byte offset. | *** #### ChunkContext [Section titled “ChunkContext”](#chunkcontext) Metadata for a single chunk of source code. | Field | Type | Default | Description | | ---------------- | ------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Language` | `string` | — | Language name used to parse this chunk. | | `ChunkIndex` | `uint` | — | Zero-indexed position of this chunk within the file’s chunk list. | | `TotalChunks` | `uint` | — | Total number of chunks the file was split into. | | `NodeTypes` | `\[\]string` | `nil` | Tree-sitter node kinds that appear at the top level of this chunk. | | `ContextPath` | `\[\]string` | `nil` | Hierarchical path of enclosing structural items (e.g., `["MyClass", "my_method"]`). | | `SymbolsDefined` | `\[\]string` | `nil` | Names of symbols defined within this chunk. | | `Comments` | `\[\]CommentInfo` | `nil` | Comments contained within this chunk. | | `Docstrings` | `\[\]DocstringInfo` | `nil` | Docstrings contained within this chunk. Populated only for Python — the same language for which `ProcessResult.docstrings` is populated, and by the same classifier. Always empty for every other language. | | `HasErrorNodes` | `bool` | — | Whether this chunk contains any tree-sitter error nodes. | *** #### CodeChunk [Section titled “CodeChunk”](#codechunk) A chunk of source code with rich metadata. | Field | Type | Default | Description | | ----------- | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `Content` | `string` | — | The raw source text of this chunk. | | `StartByte` | `uint` | — | Inclusive start byte offset of this chunk in the original source. | | `EndByte` | `uint` | — | Exclusive end byte offset of this chunk in the original source. | | `StartLine` | `uint` | — | Zero-indexed start line of this chunk. | | `EndLine` | `uint` | — | Zero-indexed row of the last byte actually included in this chunk (inclusive — the same row a `Span.end_line` would report for a node ending on that byte). Computed the same way regardless of whether the source has a trailing newline: it is always the row of `end_byte - 1`, never a phantom row past the file’s real content. | | `Metadata` | `ChunkContext` | — | Contextual metadata about this chunk. | *** #### CommentInfo [Section titled “CommentInfo”](#commentinfo) A comment extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------- | ----------------- | ----------------------------------------------------------------- | | `Text` | `string` | — | The raw text content of the comment. | | `Kind` | `CommentKind` | `CommentKindLine` | The kind of comment (line, block, or doc). | | `Span` | `Span` | — | Source span covering the comment. | | `AssociatedNode` | `*string` | `nil` | Name of the syntax node this comment is directly associated with. | *** #### DataAttribute [Section titled “DataAttribute”](#dataattribute) An XML-style attribute attached to an `Element` node. Populated only for `DataNodeKind.Element`; always empty for `KeyValue` and `Sequence` nodes. | Field | Type | Default | Description | | ------- | -------- | ------- | --------------------------------------------------------------- | | `Name` | `string` | — | Attribute name (e.g. `"class"`, `"href"`). | | `Value` | `string` | — | Attribute value as a raw string (quotes stripped). | | `Span` | `Span` | — | Source span covering the entire `name="value"` attribute token. | *** #### DataNode [Section titled “DataNode”](#datanode) A node in the hierarchical data tree produced by data-format extraction. When `ProcessConfig.data_extraction` is `true`, `ProcessResult.data` is populated with a root `DataNode` whose `children` mirror the structure of the parsed file. The `kind` field determines which other fields are meaningful: | `kind` | `key` | `value` | `attributes` | `children` | | ---------- | ------------------------- | ------------ | ------------ | -------------- | | `KeyValue` | key / mapping key / index | leaf value | empty | nested map | | `Element` | XML tag name | text content | XML attrs | child elements | | `Sequence` | positional index (`"0"`) | leaf value | empty | sub-items | | Field | Type | Default | Description | | ------------ | ------------------- | ---------------------- | ---------------------------------------------------------------------------------------------------- | | `Kind` | `DataNodeKind` | `DataNodeKindKeyValue` | Whether this node is a key/value pair, XML element, or sequence item. | | `Key` | `*string` | `nil` | Key, attribute name, tag name, or positional index (`"0"`, `"1"`, …). `nil` at the document root. | | `Value` | `*string` | `nil` | Leaf scalar value, if any. `nil` for containers (objects, arrays, XML elements with child elements). | | `Attributes` | `\[\]DataAttribute` | `nil` | Attributes on element-shape nodes (XML `STag` attributes). Empty for all other kinds. | | `Children` | `\[\]DataNode` | `nil` | Children for nested containers and XML element bodies. | | `Span` | `Span` | — | Source span covering this node in the original source file. | *** #### Diagnostic [Section titled “Diagnostic”](#diagnostic) A diagnostic (syntax error, missing node, etc.) from parsing. | Field | Type | Default | Description | | ---------- | -------------------- | ------------------------- | ---------------------------------------------- | | `Message` | `string` | — | Human-readable description of the diagnostic. | | `Severity` | `DiagnosticSeverity` | `DiagnosticSeverityError` | Severity of the diagnostic. | | `Span` | `Span` | — | Source span where the diagnostic was detected. | *** #### DocSection [Section titled “DocSection”](#docsection) A section within a docstring (e.g., Args, Returns, Raises). | Field | Type | Default | Description | | ------------- | --------- | ------- | ------------------------------------------------------- | | `Kind` | `string` | — | Section kind (e.g., `"args"`, `"returns"`, `"raises"`). | | `Name` | `*string` | `nil` | Parameter or return value name, if applicable. | | `Description` | `string` | — | Description text for this section. | *** #### DocstringInfo [Section titled “DocstringInfo”](#docstringinfo) A docstring extracted from source code. | Field | Type | Default | Description | | ---------------- | ----------------- | ---------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Text` | `string` | — | The raw text of the docstring. | | `Format` | `DocstringFormat` | `DocstringFormatPythonTripleQuote` | The docstring format (Python, JSDoc, Rustdoc, etc.). | | `Span` | `Span` | — | Source span covering the docstring. | | `AssociatedItem` | `*string` | `nil` | Name of the item this docstring documents. | | `ParsedSections` | `\[\]DocSection` | `nil` | Parsed sections of the docstring (Args, Returns, Raises, etc.). **Reserved: not yet populated.** Always empty, for every `DocstringFormat`. Parsing a docstring body into sections requires implementing each convention’s own layout (Google/NumPy/reST style for Python, `@param`/`@returns` for JSDoc/Javadoc, and so on), which no extractor here does yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | *** #### DownloadManager [Section titled “DownloadManager”](#downloadmanager) Manages downloading and caching of pre-built parser shared libraries. ##### Methods [Section titled “Methods”](#methods) ###### New() [Section titled “New()”](#new) Create a new download manager for the given version. **Errors:** Returns `Error.Download` if `version` is empty, contains a path separator or `..`, or contains a character outside `[A-Za-z0-9.+-]` — see `validate_version` — or if no cache directory can be resolved (see `Self.default_cache_dir`). **Signature:** ```go func DownloadManagerNew(version string) (*DownloadManager, error) ``` **Example:** ```go result, err := DownloadManagerNew("value") if err != nil { return err } ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ----------- | | `Version` | `string` | Yes | The version | **Returns:** `DownloadManager` **Errors:** Returns `error`. ###### InstalledLanguages() [Section titled “InstalledLanguages()”](#installedlanguages) List languages that are already downloaded and cached. Derived from the on-disk cache filenames, one canonical name per file, plus every alias that resolves to it (via `aliases_for`) — so this list agrees with the user-facing `LanguageRegistry.available_languages` about which names are “available”; both report `"shell"` once `bash` is cached, for example. A previous version reported canonical names only, which could never agree with `available_languages()`. See #107. Returns an empty list if the cache directory does not exist. If it exists but cannot be read (e.g. a permission error), also returns an empty list — changing this to a `Result` would be a breaking change across every language binding — but logs a `tracing.warn!` so the failure is not silently indistinguishable from “nothing installed”. **Signature:** ```go func (o *DownloadManager) InstalledLanguages() []string ``` **Example:** ```go result := instance.InstalledLanguages() ``` **Returns:** `[]string` ###### DownloadAllBestEffort() [Section titled “DownloadAllBestEffort()”](#downloadallbesteffort) Download the platform bundle and extract every library file it contains. Unlike `Self.ensure_languages`, this does not check the manifest language list against archive contents — it simply extracts all `.so`/`.dylib`/`.dll` files from the bundle. Languages in the manifest that are missing from the archive are silently ignored rather than returning an error. Returns the number of library files extracted (including those already cached). **Signature:** ```go func (o *DownloadManager) DownloadAllBestEffort() (uint, error) ``` **Example:** ```go result, err := instance.DownloadAllBestEffort() if err != nil { return err } ``` **Returns:** `uint` **Errors:** Returns `error`. ###### CleanCache() [Section titled “CleanCache()”](#cleancache-1) Remove all cached parser libraries. Acquires the cross-process lock so `clean_cache` cannot race a concurrent downloader (avoids Windows sharing-violation errors against an in-flight bundle write). The `.download.lock` file itself is **not** removed — it is permanent infrastructure; deleting it could allow a concurrent process that already opened the file to continue holding a stale lock handle while a new process opens a fresh inode, breaking the mutual-exclusion guarantee. **Signature:** ```go func (o *DownloadManager) CleanCache() error ``` **Example:** ```go if err := instance.CleanCache(); err != nil { return err } ``` **Returns:** No return value. **Errors:** Returns `error`. *** #### ExportInfo [Section titled “ExportInfo”](#exportinfo) An export statement extracted from source code. | Field | Type | Default | Description | | ------ | ------------ | ----------------- | -------------------------------------------------- | | `Name` | `string` | — | The exported name. | | `Kind` | `ExportKind` | `ExportKindNamed` | The kind of export (named, default, or re-export). | | `Span` | `Span` | — | Source span covering the export statement. | *** #### FileMetrics [Section titled “FileMetrics”](#filemetrics) Aggregate metrics for a source file. | Field | Type | Default | Description | | -------------- | ------ | ------- | -------------------------------------------------------------- | | `TotalLines` | `uint` | — | Total number of lines (including blank and comment lines). | | `CodeLines` | `uint` | — | Number of lines containing non-blank, non-comment source code. | | `CommentLines` | `uint` | — | Number of lines that are entirely comments. | | `BlankLines` | `uint` | — | Number of blank (whitespace-only) lines. | | `TotalBytes` | `uint` | — | Total byte length of the source file. | | `NodeCount` | `uint` | — | Total number of nodes in the syntax tree. | | `ErrorCount` | `uint` | — | Number of error nodes in the syntax tree (parse errors). | | `MaxDepth` | `uint` | — | Maximum nesting depth reached in the syntax tree. | *** #### ImportInfo [Section titled “ImportInfo”](#importinfo) An import statement extracted from source code. | Field | Type | Default | Description | | ------------ | ------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `Source` | `string` | — | The module or path being imported from. | | `Items` | `\[\]string` | `nil` | Specific names imported from the source module. For `import a, b` / `from m import a, b`, every entry’s base name (never the alias). For a JavaScript/TypeScript named-imports clause (`import { a, b as c } from 'm'`), every specifier’s original name. Populated for Python and JavaScript/TypeScript only. Always empty for every other language this library recognises import statements for — Rust, Go, Java, Kotlin, and Elixir (`import`/`alias`/`require`/`use`) — and for a JS/TS namespace import (`import * as ns`) or default import (`import x from 'm'`), neither of which names individual items. | | `Alias` | `*string` | `nil` | Alias assigned to the import (e.g., `import numpy as np`). Populated for Python’s single-name form (`import numpy as np`, `from m import a as b`) and JavaScript/TypeScript’s namespace form (`import * as ns from 'm'`) or a named-imports clause naming exactly one specifier (`import { a as b } from 'm'`). `nil` for Rust, Go, Java, Kotlin, and Elixir (which has its own `as:` alias option on `alias` directives, not yet extracted here) — and for a Python statement that aliases several names at once (`import os, sys as s`), where there is no single alias to report for the statement as a whole, so only `items` is populated for it. | | `IsWildcard` | `bool` | — | Whether this is a wildcard import (e.g., `import *` or `use foo.*`). Detected from the syntax tree — a dedicated wildcard node (`wildcard_import` in Python, `use_wildcard` in Rust) or a bare `*` token outside of string-literal content — not by searching the import’s source text for a `*` character, so a glob in an import path string (`import a from './glob*.js'`) is not mistaken for one. | | `Span` | `Span` | — | Source span covering the import statement. | *** #### Language [Section titled “Language”](#language) *** #### LanguageRegistry [Section titled “LanguageRegistry”](#languageregistry) Thread-safe registry of tree-sitter language parsers. Manages both statically compiled and dynamically loaded language grammars. Use `LanguageRegistry.new()` for the default registry, or access the global instance via the module-level convenience functions (`get_language`, `available_languages`, etc.). ##### Methods [Section titled “Methods”](#methods-1) ###### New() [Section titled “New()”](#new-1) Create a new registry populated with all statically compiled languages. When the `dynamic-loading` feature is enabled, the registry also knows about dynamically loadable grammars and will load them on demand. **Signature:** ```go func LanguageRegistryNew() *LanguageRegistry ``` **Example:** ```go result := LanguageRegistryNew() ``` **Returns:** `LanguageRegistry` ###### GetLanguage() [Section titled “GetLanguage()”](#getlanguage-1) Get a tree-sitter `Language` by name. Resolves aliases (e.g., `"shell"` -> `"bash"`, `"makefile"` -> `"make"`), then looks up the language in the static table. When the `dynamic-loading` feature is enabled, falls back to loading a shared library on demand. **Errors:** Returns `Error.LanguageNotFound` if the name (after alias resolution) does not match any known grammar. **Signature:** ```go func (o *LanguageRegistry) GetLanguage(name string) (*Language, error) ``` **Example:** ```go result, err := instance.GetLanguage("value") if err != nil { return err } ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** `Language` **Errors:** Returns `error`. ###### AvailableLanguages() [Section titled “AvailableLanguages()”](#availablelanguages-1) List all available language names, sorted and deduplicated. Includes statically compiled languages, dynamically loadable languages (if the `dynamic-loading` feature is enabled), and all configured aliases. **Signature:** ```go func (o *LanguageRegistry) AvailableLanguages() []string ``` **Example:** ```go result := instance.AvailableLanguages() ``` **Returns:** `[]string` ###### HasParser() [Section titled “HasParser()”](#hasparser) Check whether this language can be parsed right now, without downloading. Resolves aliases, then answers from exactly the lookup `get_language` performs: the statically compiled table, the already-loaded dynamic grammars, and the parser shared libraries present in the primary and extra (download-cache) library directories. It never performs network I/O. A previous implementation consulted only the statically compiled table. That table is empty in every build that does not set `TSLP_LANGUAGES`, so the function answered `false` for languages this registry parses perfectly well. Contrast `has_language`, which is also `true` for a grammar that is merely *known to the manifest* and would have to be downloaded first. The pair distinguishes “we can parse it offline, now” from “we recognise the name”. The first `true` answer for a dynamic grammar loads its shared library: loading is the only way to know the grammar is usable, since a truncated or wrong-architecture library exists on disk but cannot parse. Loads are cached process-wide, so repeat calls are cheap. **Signature:** ```go func (o *LanguageRegistry) HasParser(name string) bool ``` **Example:** ```go result := instance.HasParser("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** `bool` ###### HasLanguage() [Section titled “HasLanguage()”](#haslanguage-1) Check whether a language is available by name or alias. Returns `true` if the language can be loaded, either from the static table or from a dynamic library on disk. Every branch is one more way to answer `true`, so they are ordered cheapest-first and the filesystem is only consulted once every in-memory source has said no. Probing the loaded-grammar map and the manifest ahead of the `stat` calls is what keeps this off the syscall path for the languages a process actually uses. **Signature:** ```go func (o *LanguageRegistry) HasLanguage(name string) bool ``` **Example:** ```go result := instance.HasLanguage("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** `bool` ###### LanguageCount() [Section titled “LanguageCount()”](#languagecount-1) Return the total number of available languages (including aliases). Counts the same set `available_languages` lists, without materialising or sorting it. **Signature:** ```go func (o *LanguageRegistry) LanguageCount() uint ``` **Example:** ```go result := instance.LanguageCount() ``` **Returns:** `uint` ###### Process() [Section titled “Process()”](#process-1) Parse source code and extract file intelligence based on config in a single pass. **Errors:** Returns `Error.InvalidRange` if the config is invalid (see `ProcessConfig.validate`) or if the source exceeds the configured `max_source_bytes`; `Error.LanguageNotFound` if the language is unknown; or `Error.ParseFailed` if parsing produces no tree. **Signature:** ```go func (o *LanguageRegistry) Process(source string, config ProcessConfig) (*ProcessResult, error) ``` **Example:** ```go result, err := instance.Process("value", ProcessConfig{}) if err != nil { return err } ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `Source` | `string` | Yes | The source | | `Config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Returns `error`. *** #### Node [Section titled “Node”](#node) A single syntax node within a `Tree`. Nodes hold a strong reference to their parent tree so they remain valid regardless of how the tree is moved or stored at the FFI boundary. ##### Methods [Section titled “Methods”](#methods-2) ###### Kind() [Section titled “Kind()”](#kind) Return the node’s kind name (e.g. `"function_definition"`). **Signature:** ```go func (o *Node) Kind() string ``` **Example:** ```go result := instance.Kind() ``` **Returns:** `string` ###### KindId() [Section titled “KindId()”](#kindid) Return the node’s numeric kind ID. Tree-sitter assigns a stable `u16` ID to every node kind in a grammar (e.g. `"function_definition" → 42`). Comparing `kind_id()` is cheaper than comparing the string `kind()` in tight AST loops. **Signature:** ```go func (o *Node) KindId() uint16 ``` **Example:** ```go result := instance.KindId() ``` **Returns:** `uint16` ###### StartByte() [Section titled “StartByte()”](#startbyte) Return the inclusive start byte offset of this node. **Signature:** ```go func (o *Node) StartByte() uint ``` **Example:** ```go result := instance.StartByte() ``` **Returns:** `uint` ###### EndByte() [Section titled “EndByte()”](#endbyte) Return the exclusive end byte offset of this node. **Signature:** ```go func (o *Node) EndByte() uint ``` **Example:** ```go result := instance.EndByte() ``` **Returns:** `uint` ###### ByteRange() [Section titled “ByteRange()”](#byterange-1) Return the node’s byte range as a `ByteRange`. Callers should slice their own source bytes — this is a zero-copy text accessor. **Signature:** ```go func (o *Node) ByteRange() *ByteRange ``` **Example:** ```go result := instance.ByteRange() ``` **Returns:** `ByteRange` ###### StartPosition() [Section titled “StartPosition()”](#startposition) Return the start `Point` (row, column). **Signature:** ```go func (o *Node) StartPosition() *Point ``` **Example:** ```go result := instance.StartPosition() ``` **Returns:** `Point` ###### EndPosition() [Section titled “EndPosition()”](#endposition) Return the end `Point` (row, column). **Signature:** ```go func (o *Node) EndPosition() *Point ``` **Example:** ```go result := instance.EndPosition() ``` **Returns:** `Point` ###### IsNamed() [Section titled “IsNamed()”](#isnamed) True when this node is named (not punctuation/whitespace). **Signature:** ```go func (o *Node) IsNamed() bool ``` **Example:** ```go result := instance.IsNamed() ``` **Returns:** `bool` ###### IsError() [Section titled “IsError()”](#iserror) True when this is an error node. **Signature:** ```go func (o *Node) IsError() bool ``` **Example:** ```go result := instance.IsError() ``` **Returns:** `bool` ###### IsMissing() [Section titled “IsMissing()”](#ismissing) True when this is a missing-token node. **Signature:** ```go func (o *Node) IsMissing() bool ``` **Example:** ```go result := instance.IsMissing() ``` **Returns:** `bool` ###### IsExtra() [Section titled “IsExtra()”](#isextra) True when this is an “extra” node (e.g. a comment). **Signature:** ```go func (o *Node) IsExtra() bool ``` **Example:** ```go result := instance.IsExtra() ``` **Returns:** `bool` ###### HasError() [Section titled “HasError()”](#haserror) True when this node or any descendant is an error. **Signature:** ```go func (o *Node) HasError() bool ``` **Example:** ```go result := instance.HasError() ``` **Returns:** `bool` ###### Parent() [Section titled “Parent()”](#parent) Return this node’s parent, if any. **Signature:** ```go func (o *Node) Parent() *Node ``` **Example:** ```go result := instance.Parent() ``` **Returns:** `*Node` ###### Child() [Section titled “Child()”](#child) Return the i-th child of this node, if any. **Signature:** ```go func (o *Node) Child(index uint32) *Node ``` **Example:** ```go result := instance.Child(42) ``` **Parameters:** | Name | Type | Required | Description | | ------- | -------- | -------- | ----------- | | `Index` | `uint32` | Yes | The index | **Returns:** `*Node` ###### ChildCount() [Section titled “ChildCount()”](#childcount) Total number of children (including unnamed). **Signature:** ```go func (o *Node) ChildCount() uint ``` **Example:** ```go result := instance.ChildCount() ``` **Returns:** `uint` ###### NamedChild() [Section titled “NamedChild()”](#namedchild) Return the i-th named child of this node, if any. **Signature:** ```go func (o *Node) NamedChild(index uint32) *Node ``` **Example:** ```go result := instance.NamedChild(42) ``` **Parameters:** | Name | Type | Required | Description | | ------- | -------- | -------- | ----------- | | `Index` | `uint32` | Yes | The index | **Returns:** `*Node` ###### NamedChildCount() [Section titled “NamedChildCount()”](#namedchildcount) Number of named children of this node. **Signature:** ```go func (o *Node) NamedChildCount() uint ``` **Example:** ```go result := instance.NamedChildCount() ``` **Returns:** `uint` ###### ChildByFieldName() [Section titled “ChildByFieldName()”](#childbyfieldname) Look up a child by its grammar-defined field name. **Signature:** ```go func (o *Node) ChildByFieldName(name string) *Node ``` **Example:** ```go result := instance.ChildByFieldName("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** `*Node` ###### ToSexp() [Section titled “ToSexp()”](#tosexp) Return the S-expression form of this node’s subtree. **Signature:** ```go func (o *Node) ToSexp() string ``` **Example:** ```go result := instance.ToSexp() ``` **Returns:** `string` ###### Walk() [Section titled “Walk()”](#walk) Return a `TreeCursor` positioned at this node. **Signature:** ```go func (o *Node) Walk() *TreeCursor ``` **Example:** ```go result := instance.Walk() ``` **Returns:** `TreeCursor` *** #### PackConfig [Section titled “PackConfig”](#packconfig) Configuration for the tree-sitter language pack. Controls cache directory and which languages to pre-download. Can be loaded from a TOML file, constructed programmatically, or passed as a dict/object from language bindings. | Field | Type | Default | Description | | ----------- | ------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `CacheDir` | `*string` | `nil` | Override the BASE directory the parser cache lives under. This is a base, not the final library path: the crate appends `tree-sitter-language-pack/v{version}/libs` to it, exactly as it does to the platform default. So `cache_dir = "/tmp/my-parsers"` resolves to `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`. The suffix is not cosmetic. It keeps the whole cache tree — manifest, bundles and lock file included — inside a directory this library owns and versions. Earlier releases used this path verbatim, which put those files in the configured directory’s PARENT and let a cache built by one crate version be reused by another. Default base: the platform cache dir, e.g. `~/.cache` on Linux. | | `Languages` | `*\[\]string` | `nil` | Languages to pre-download on init. Each entry is a language name (e.g. `"python"`, `"rust"`). | | `Groups` | `*\[\]string` | `nil` | Language groups to pre-download. Group names come from the remote manifest, so the valid set is not fixed by this library; the published manifest currently defines only `"all"`. Call `manifest_groups` to enumerate them. An unknown name makes `init` fail. | *** #### Parser [Section titled “Parser”](#parser) A tree-sitter parser configured for one language at a time. ##### Methods [Section titled “Methods”](#methods-3) ###### New() [Section titled “New()”](#new-2) Construct a new parser with no language set and no parse limits. Call `Parser.set_language` before parsing. Limits are opt-in via `set_max_source_bytes` and `set_parse_timeout_ms`; both default to unbounded so that existing callers are unaffected. **Signature:** ```go func ParserNew() *Parser ``` **Example:** ```go result := ParserNew() ``` **Returns:** `Parser` ###### SetMaxSourceBytes() [Section titled “SetMaxSourceBytes()”](#setmaxsourcebytes) Refuse to parse sources longer than `max_bytes`. `nil` (the default) means no limit. Over-limit input makes `parse` and `parse_bytes` return `nil` after emitting a `WARN`; input is never silently truncated. See `RECOMMENDED_MAX_SOURCE_BYTES`. **Signature:** ```go func (o *Parser) SetMaxSourceBytes(maxBytes uint) ``` **Example:** ```go instance.SetMaxSourceBytes(42) ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------- | -------- | ------------- | | `MaxBytes` | `*uint` | No | The max bytes | **Returns:** No return value. ###### SetParseTimeoutMs() [Section titled “SetParseTimeoutMs()”](#setparsetimeoutms) Cancel a parse that exceeds `timeout_ms` milliseconds of wall clock. `nil` (the default) means no budget. Cancellation runs through tree-sitter’s parse progress callback, so it is granular to that callback’s interval rather than exact. See `RECOMMENDED_PARSE_TIMEOUT_MS`. **Signature:** ```go func (o *Parser) SetParseTimeoutMs(timeoutMs uint64) ``` **Example:** ```go instance.SetParseTimeoutMs(42) ``` **Parameters:** | Name | Type | Required | Description | | ----------- | --------- | -------- | -------------- | | `TimeoutMs` | `*uint64` | No | The timeout ms | **Returns:** No return value. ###### SetLanguage() [Section titled “SetLanguage()”](#setlanguage) Configure the parser to use the language identified by name (e.g. `"python"`). Resolves the language through the global registry — auto-downloading if necessary, when the `download` feature is enabled. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language ABI is incompatible. **Signature:** ```go func (o *Parser) SetLanguage(name string) error ``` **Example:** ```go if err := instance.SetLanguage("value"); err != nil { return err } ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `Name` | `string` | Yes | The name | **Returns:** No return value. **Errors:** Returns `error`. ###### Parse() [Section titled “Parse()”](#parse) Parse a UTF-8 source string. Returns `nil` if no language is set, if the parse was cancelled by the configured timeout, or if the source exceeds the configured size limit. Each non-parse outcome is logged, so an empty result is never silent. ###### Concurrency [Section titled “Concurrency”](#concurrency) Parsing runs fully in parallel across threads for almost every language — no lock is taken. The exception is the small set of grammars whose external scanner keeps mutable process-global state (currently just `properties`): parses of that language are serialized against each other through an internal per-language lock, so that concurrent threads can’t corrupt shared scanner state. Every other language is unaffected by that lock and never waits on it. **Signature:** ```go func (o *Parser) Parse(source string) *Tree ``` **Example:** ```go result := instance.Parse("value") ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------- | -------- | ----------- | | `Source` | `string` | Yes | The source | **Returns:** `*Tree` ###### ParseBytes() [Section titled “ParseBytes()”](#parsebytes) Parse a raw byte slice. Same outcomes as `parse`, including the concurrency behaviour documented there. **Signature:** ```go func (o *Parser) ParseBytes(source []byte) *Tree ``` **Example:** ```go result := instance.ParseBytes([]byte("data")) ``` **Parameters:** | Name | Type | Required | Description | | -------- | ---------- | -------- | ----------- | | `Source` | `\[\]byte` | Yes | The source | **Returns:** `*Tree` ###### Reset() [Section titled “Reset()”](#reset) Reset internal state. The next call to `parse` will not be incremental. **Signature:** ```go func (o *Parser) Reset() ``` **Example:** ```go instance.Reset() ``` **Returns:** No return value. *** #### Point [Section titled “Point”](#point) A source position — row + column, zero-indexed. | Field | Type | Default | Description | | -------- | ------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `Row` | `uint` | — | Zero-indexed row number. | | `Column` | `uint` | — | Zero-indexed column, counted in **bytes** from the start of the row. This is `tree_sitter.Point.column` verbatim, and tree-sitter defines it as a byte offset — not characters, and not UTF-16 code units. Measured on a row of the form `x = ''` where `` is a single 4-byte character (an emoji), the string node reports columns `4..10`, identical to its byte range; the character columns would be `4..7` and the UTF-16 columns `4..8`. Anything that builds LSP positions (UTF-16) or editor caret columns (characters) from this field is silently wrong on every row containing a non-ASCII byte, and must re-measure the row against the source text instead. Earlier releases documented this field as UTF-16 code units; that was never what the value contained. | *** #### ProcessConfig [Section titled “ProcessConfig”](#processconfig) Configuration for the `process()` function. Controls which analysis features are enabled and whether chunking is performed. | Field | Type | Default | Description | | ---------------- | --------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Language` | `string` | `""` | Language name (required). | | `Structure` | `bool` | `true` | Extract structural items (functions, classes, etc.). Default: true. | | `Imports` | `bool` | `true` | Extract import statements. Default: true. | | `Exports` | `bool` | `true` | Extract export statements. Default: true. | | `Comments` | `bool` | `false` | Extract comments. Default: false. | | `Docstrings` | `bool` | `false` | Extract docstrings. Default: false. | | `Symbols` | `bool` | `false` | Extract symbol definitions. Default: false. | | `Diagnostics` | `bool` | `false` | Include parse diagnostics. Default: false. | | `ChunkMaxSize` | `*uint` | `nil` | Maximum chunk size in bytes. `nil` disables chunking. `Some(0)` is rejected by `ProcessConfig.validate` with `Error.InvalidRange`. A zero-sized chunk limit previously produced an empty chunk list and silently discarded the whole source; use `nil` to mean “do not chunk”. | | `DataExtraction` | `bool` | `false` | Extract hierarchical key/value data tree from data-format files. Default: false. When `true`, `ProcessResult.data` is populated with a `DataNode` tree for supported languages: JSON, YAML, TOML, `.properties`, HCL/HOCON, INI, editorconfig, KDL, CUE, CSV, PSV, PO, nginx config, Caddy config, XML, and DTD. For languages outside this set the field is left as `nil`. | | `MaxSourceBytes` | `*uint` | `nil` | Reject source longer than this many bytes instead of parsing it. Default: `nil` (unbounded). Tree-sitter allocates and walks proportionally to input size, so an unbounded parse of attacker-supplied input is a denial-of-service vector. The default stays unbounded for backward compatibility; services handling untrusted input should opt in, e.g. with `RECOMMENDED_MAX_SOURCE_BYTES`. Exceeding the limit fails the call with `Error.InvalidRange` — the source is never silently truncated. | | `ParseTimeoutMs` | `*uint64` | `nil` | Wall-clock budget for the parse step, in milliseconds. Default: `nil` (no timeout). Enforced through tree-sitter’s parse progress callback, which the parser invokes periodically; cancellation is therefore granular to that callback interval rather than exact. A parse that exceeds the budget fails with `Error.ParseTimeout`. | ##### Methods [Section titled “Methods”](#methods-4) ###### WithChunking() [Section titled “WithChunking()”](#withchunking) Enable chunking with the given maximum chunk size in bytes. **Signature:** ```go func (o *ProcessConfig) WithChunking(maxSize uint) *ProcessConfig ``` **Example:** ```go result := instance.WithChunking(42) ``` **Parameters:** | Name | Type | Required | Description | | --------- | ------ | -------- | ------------ | | `MaxSize` | `uint` | Yes | The max size | **Returns:** `ProcessConfig` ###### All() [Section titled “All()”](#all) Enable every analysis feature, including data extraction. Chunking is not an analysis feature and stays off; enable it with `with_chunking`. **Signature:** ```go func (o *ProcessConfig) All() *ProcessConfig ``` **Example:** ```go result := instance.All() ``` **Returns:** `ProcessConfig` ###### Minimal() [Section titled “Minimal()”](#minimal) Disable all analysis features (only metrics computed). **Signature:** ```go func (o *ProcessConfig) Minimal() *ProcessConfig ``` **Example:** ```go result := instance.Minimal() ``` **Returns:** `ProcessConfig` ###### WithDataExtraction() [Section titled “WithDataExtraction()”](#withdataextraction) Enable or disable hierarchical data extraction for data-format files. When `true`, `ProcessResult.data` is populated with a key/value tree for supported data-format languages. **Signature:** ```go func (o *ProcessConfig) WithDataExtraction(enabled bool) *ProcessConfig ``` **Example:** ```go result := instance.WithDataExtraction(true) ``` **Parameters:** | Name | Type | Required | Description | | --------- | ------ | -------- | ----------- | | `Enabled` | `bool` | Yes | The enabled | **Returns:** `ProcessConfig` ###### WithMaxSourceBytes() [Section titled “WithMaxSourceBytes()”](#withmaxsourcebytes) Reject source longer than `max_bytes` instead of parsing it. Pass `nil` to restore the default unbounded behaviour. See `RECOMMENDED_MAX_SOURCE_BYTES` for a starting value. **Signature:** ```go func (o *ProcessConfig) WithMaxSourceBytes(maxBytes uint) *ProcessConfig ``` **Example:** ```go result := instance.WithMaxSourceBytes(42) ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------- | -------- | ------------- | | `MaxBytes` | `*uint` | No | The max bytes | **Returns:** `ProcessConfig` ###### WithParseTimeoutMs() [Section titled “WithParseTimeoutMs()”](#withparsetimeoutms) Cancel the parse if it exceeds `timeout_ms` milliseconds of wall clock. Pass `nil` to restore the default (no timeout). See `RECOMMENDED_PARSE_TIMEOUT_MS` for a starting value. **Signature:** ```go func (o *ProcessConfig) WithParseTimeoutMs(timeoutMs uint64) *ProcessConfig ``` **Example:** ```go result := instance.WithParseTimeoutMs(42) ``` **Parameters:** | Name | Type | Required | Description | | ----------- | --------- | -------- | -------------- | | `TimeoutMs` | `*uint64` | No | The timeout ms | **Returns:** `ProcessConfig` ###### Validate() [Section titled “Validate()”](#validate) Check that the configured limits are usable before they drive a parse. Called by `process` and `LanguageRegistry.process`; call it directly to reject a bad configuration early. **Errors:** Returns `Error.InvalidRange` when `chunk_max_size`, `max_source_bytes`, or `parse_timeout_ms` is `Some(0)`. Zero is always a configuration mistake: `nil` is how each of these is disabled, so `Some(0)` could only mean “produce nothing”. **Signature:** ```go func (o *ProcessConfig) Validate() error ``` **Example:** ```go if err := instance.Validate(); err != nil { return err } ``` **Returns:** No return value. **Errors:** Returns `error`. *** #### ProcessResult [Section titled “ProcessResult”](#processresult) Complete analysis result from processing a source file. Contains metrics, structural analysis, imports/exports, comments, docstrings, symbols, diagnostics, and optionally chunked code segments. Fields are populated based on the `ProcessConfig` flags. | Field | Type | Default | Description | | ------------- | ------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Language` | `string` | — | The language name used to parse the source file. | | `Metrics` | `FileMetrics` | — | File-level metrics (line counts, byte size, error count). | | `Structure` | `\[\]StructureItem` | `nil` | Top-level structural items (functions, classes, etc.). | | `Imports` | `\[\]ImportInfo` | `nil` | Import statements extracted from the source. | | `Exports` | `\[\]ExportInfo` | `nil` | Export statements extracted from the source. | | `Comments` | `\[\]CommentInfo` | `nil` | Comments extracted from the source. | | `Docstrings` | `\[\]DocstringInfo` | `nil` | Docstrings extracted from the source. | | `Symbols` | `\[\]SymbolInfo` | `nil` | Symbol definitions (variables, types, functions) extracted from the source. | | `Diagnostics` | `\[\]Diagnostic` | `nil` | Parse diagnostics (syntax errors, missing nodes) from tree-sitter. | | `Chunks` | `\[\]CodeChunk` | `nil` | Syntax-aware code chunks produced when chunking is enabled. | | `Data` | `*DataNode` | `nil` | Hierarchical data tree extracted when `config.data_extraction` is `true`. Populated for supported data-format languages (JSON, YAML, TOML, properties, HCL, INI, XML, CSV, and more). `nil` when `data_extraction` is `false` (the default) or when the language is not a recognised data format. See `DataNode` for the shape of the returned tree. | *** #### Span [Section titled “Span”](#span) Byte and line/column range in source code. Represents both byte offsets (for slicing) and human-readable line/column positions (for display and diagnostics). | Field | Type | Default | Description | | ------------- | ------ | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `StartByte` | `uint` | — | Inclusive start byte offset in the source. | | `EndByte` | `uint` | — | Exclusive end byte offset in the source. | | `StartLine` | `uint` | — | Zero-indexed line number of the span’s start. | | `StartColumn` | `uint` | — | Zero-indexed column of the span’s start, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | | `EndLine` | `uint` | — | Zero-indexed line number of the span’s end. | | `EndColumn` | `uint` | — | Zero-indexed column of the span’s end, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | *** #### StructureItem [Section titled “StructureItem”](#structureitem) A structural item (function, class, struct, etc.) in source code. | Field | Type | Default | Description | | ------------ | ------------------- | ----------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Kind` | `StructureKind` | `StructureKindFunction` | The kind of structural item. | | `Name` | `*string` | `nil` | The declared name of the item, if present. | | `Visibility` | `*string` | `nil` | Visibility modifier (e.g., `"pub"`, `"public"`, `"private"`). | | `Span` | `Span` | — | Source span covering the entire item declaration. | | `Children` | `\[\]StructureItem` | `nil` | Nested structural items (e.g., methods within a class). | | `Decorators` | `\[\]string` | `nil` | Decorator or attribute names applied to the item. **Reserved: not yet populated.** Always empty, for every language. Recognising a decorator requires per-language grammar knowledge (a Python `decorated_definition` wrapper, Java/C# annotations, Rust attributes each have a different shape), which no extractor here implements yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | | `DocComment` | `*string` | `nil` | Documentation comment attached to the item, if any. The text of the comment (or run of comments) immediately preceding the item, with no blank line in between, when that comment is classified as a doc comment. Multiple adjacent single-line doc comments (Rust `///`) are joined with `\n` in source order. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`). `nil` for every other language, and for a preceding comment that is not in doc-comment form (a plain `#` comment in Python, Ruby, or Elixir) — Python’s docstring convention is captured separately, as `DocstringInfo`, not through this field. | | `Signature` | `*string` | `nil` | Full signature text of the item (e.g., function parameters and return type). The item’s own source text from its start up to the start of its body (see `StructureItem.body_span`), trimmed of trailing whitespace — for example `fn add(a: i32, b: i32) -> i32` for a Rust function whose body is `{ a + b }`. `nil` only when that text is empty, which does not happen for any item `StructureKind` currently reports. Populated for every language and kind this library extracts structure for, since it is derived from `body_span`’s boundary rather than per-language syntax. | | `BodySpan` | `*Span` | `nil` | Source span covering only the body of the item, if distinct from the declaration. | *** #### SymbolInfo [Section titled “SymbolInfo”](#symbolinfo) A symbol (variable, function, type, etc.) extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------ | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `Name` | `string` | — | The name of the symbol. | | `Kind` | `SymbolKind` | `SymbolKindVariable` | The kind of symbol (variable, function, class, etc.). | | `Span` | `Span` | — | Source span covering the symbol definition. | | `TypeAnnotation` | `*string` | `nil` | Explicit type annotation, if present in the source. | | `Doc` | `*string` | `nil` | Documentation comment immediately preceding this symbol, resolved by the same walk `StructureItem.doc_comment` uses (see `doc_comment_at`) — never hard-coded `nil`. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`) — the languages whose comment classification recognizes a doc-kind comment. `nil` for every other language (e.g. Python, Go, Ruby, which have no doc-kind comment classification), and also `nil` when a symbol in a supported language simply has no doc comment immediately above it. | *** #### Tree [Section titled “Tree”](#tree) A parsed syntax tree. Cheap to clone (refcount bump). ##### Methods [Section titled “Methods”](#methods-5) ###### RootNode() [Section titled “RootNode()”](#rootnode) Return the root `Node` of this tree. **Signature:** ```go func (o *Tree) RootNode() *Node ``` **Example:** ```go result := instance.RootNode() ``` **Returns:** `Node` ###### Walk() [Section titled “Walk()”](#walk-1) Return a `TreeCursor` positioned at the root. **Signature:** ```go func (o *Tree) Walk() *TreeCursor ``` **Example:** ```go result := instance.Walk() ``` **Returns:** `TreeCursor` *** #### TreeCursor [Section titled “TreeCursor”](#treecursor) A cursor for traversing a `Tree`. ##### Methods [Section titled “Methods”](#methods-6) ###### Node() [Section titled “Node()”](#node-1) Return the `Node` at the cursor’s current position. **Signature:** ```go func (o *TreeCursor) Node() *Node ``` **Example:** ```go result := instance.Node() ``` **Returns:** `Node` ###### GotoFirstChild() [Section titled “GotoFirstChild()”](#gotofirstchild) Move the cursor to the first child of the current node. Returns `true` if a child existed. **Signature:** ```go func (o *TreeCursor) GotoFirstChild() bool ``` **Example:** ```go result := instance.GotoFirstChild() ``` **Returns:** `bool` ###### GotoParent() [Section titled “GotoParent()”](#gotoparent) Move the cursor to the parent of the current node. Returns `true` if a parent existed. **Signature:** ```go func (o *TreeCursor) GotoParent() bool ``` **Example:** ```go result := instance.GotoParent() ``` **Returns:** `bool` ###### GotoNextSibling() [Section titled “GotoNextSibling()”](#gotonextsibling) Move the cursor to the next sibling of the current node. Returns `true` if a sibling existed. **Signature:** ```go func (o *TreeCursor) GotoNextSibling() bool ``` **Example:** ```go result := instance.GotoNextSibling() ``` **Returns:** `bool` ###### FieldName() [Section titled “FieldName()”](#fieldname) Return the field name for the current node, if any. **Signature:** ```go func (o *TreeCursor) FieldName() *string ``` **Example:** ```go result := instance.FieldName() ``` **Returns:** `*string` *** ### Enums [Section titled “Enums”](#enums) #### DataNodeKind [Section titled “DataNodeKind”](#datanodekind) The kind of a data node extracted from a data-format file. Classifies each node in the hierarchical `DataNode` tree returned when `data_extraction` is enabled on `ProcessConfig`. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract) Unit variants serialize as a bare string (`"KeyValue"`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ---------- | -------------------------------------------------------------------------------------------------------------------- | | `KeyValue` | A key/value pair or mapping (json/toml/properties/yaml/hcl/cue/kdl pair, or a wrapper “object”/“mapping” container). | | `Element` | An XML element with a tag name in `key` and attributes in `attributes`. | | `Sequence` | A positional sequence item (JSON array element, YAML block sequence item, CSV/PSV row or cell). | *** #### StructureKind [Section titled “StructureKind”](#structurekind) The kind of structural item found in source code. Categorizes top-level and nested declarations such as functions, classes, structs, enums, traits, and more. Use `Other` for language-specific constructs that do not fit a standard category. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-1) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | ---------------------------------------------------------------------------------------------- | | `Function` | A free-standing or associated function. | | `Method` | A method defined inside a class, struct, trait, or impl block. | | `Class` | A class definition. | | `Struct` | A struct definition. | | `Interface` | An interface or protocol definition. | | `Enum` | An enum definition. | | `Module` | A module or package declaration. | | `Trait` | A trait definition. | | `Impl` | An impl block (Rust) or similar implementation block. | | `Namespace` | A namespace declaration. | | `Other` | A language-specific construct that does not fit any standard category. — Fields: `0`: `string` | *** #### CommentKind [Section titled “CommentKind”](#commentkind) The kind of a comment found in source code. Distinguishes between single-line comments, block (multi-line) comments, and documentation comments. | Value | Description | | ------- | --------------------------------------------------------------------- | | `Line` | A single-line comment (e.g., `// ...` or `# ...`). | | `Block` | A block or multi-line comment using slash-star delimiters. | | `Doc` | A documentation comment such as `/// ...` or slash-double-star block. | *** #### DocstringFormat [Section titled “DocstringFormat”](#docstringformat) The format of a docstring extracted from source code. Identifies the docstring convention used, which varies by language (e.g., Python triple-quoted strings, JSDoc, Rustdoc `///` comments). ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-2) Unit variants serialize as a bare string (`"JSDoc"`); the `Other` variant serializes as a single-keyed object (`{"Other": "rst"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ------------------- | -------------------------------------------------------------------------------------------------- | | `PythonTripleQuote` | Python triple-quoted string docstring (`"""..."""`). | | `JsDoc` | JavaScript/TypeScript JSDoc block comment (opens with two stars, closes with star-slash). | | `Rustdoc` | Rust `///` or `//!` doc comment. | | `GoDoc` | Go doc comment (a comment block immediately preceding a declaration). | | `JavaDoc` | Java Javadoc block comment (opens with two stars, closes with star-slash). | | `Other` | A language-specific docstring format not covered by the standard variants. — Fields: `0`: `string` | *** #### ExportKind [Section titled “ExportKind”](#exportkind) The kind of an export statement found in source code. Covers named exports, default exports, and re-exports from other modules. | Value | Description | | ---------- | -------------------------------------------------------------------- | | `Named` | A named export (e.g., `export { foo }`). | | `Default` | A default export (e.g., `export default foo`). | | `ReExport` | A re-export from another module (e.g., `export { foo } from 'bar'`). | *** #### SymbolKind [Section titled “SymbolKind”](#symbolkind) The kind of a symbol definition found in source code. Categorizes symbol definitions such as variables, constants, functions, classes, types, interfaces, enums, and modules. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-3) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | --------------------------------------------------------------------------- | | `Variable` | A variable binding. | | `Constant` | A constant (immutable binding). | | `Function` | A function definition. | | `Class` | A class definition. | | `Type` | A type alias or typedef. | | `Interface` | An interface definition. | | `Enum` | An enum definition. | | `Module` | A module declaration. | | `Other` | A symbol kind not covered by the standard variants. — Fields: `0`: `string` | *** #### DiagnosticSeverity [Section titled “DiagnosticSeverity”](#diagnosticseverity) Severity level of a diagnostic produced during parsing. Used to classify parse errors, warnings, and informational messages found in the syntax tree. | Value | Description | | --------- | --------------------------------------------------------------- | | `Error` | A parse error (e.g., an `ERROR` or `MISSING` node in the tree). | | `Warning` | A warning-level diagnostic. | | `Info` | An informational diagnostic. | *** ### Errors [Section titled “Errors”](#errors) #### Error [Section titled “Error”](#error) Errors that can occur when using the tree-sitter language pack. Covers language lookup failures, parse errors, query errors, and I/O issues. Feature-gated variants are included when `config`, `download`, or related features are enabled. ##### Matching on `Error` [Section titled “Matching on Error”](#matching-on-error) The set of variants is not stable: new failure modes are added in minor releases, and `Io`, `Json`, and `Toml` exist only under certain feature combinations, so the variant set a downstream crate sees depends on which features it enables. Downstream `match`es must therefore carry a `_` arm; `#[non_exhaustive]` makes the compiler enforce that instead of letting a feature change silently break a build. ##### C ABI error codes [Section titled “C ABI error codes”](#c-abi-error-codes) Each variant alef can see carries an explicit `alef(error_code = N)` allocation that becomes a member of the generated `AlefFfiErrorCode` C enum. These numbers are a public ABI contract: **an allocated number is never reused after its variant is removed**, and a variant’s number never changes, because C callers compare against the value, not the name. New variants take the next free number. 0-4 are reserved by alef, so allocation starts at 100. An unannotated variant is emitted as the unknown code rather than as itself, which silently flattens the taxonomy — annotate every new variant. | Variant | Description | | ------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `ErrLanguageNotFound` | The requested language name (or alias) was not found in the registry. | | `ErrDynamicLoad` | A dynamic shared library could not be loaded at runtime. | | `ErrNullLanguagePointer` | The tree-sitter language function returned a null pointer for the given language name. | | `ErrParserSetup` | The language could not be applied to the parser (e.g., ABI version mismatch). | | `ErrLockPoisoned` | An internal `RwLock` or `Mutex` was poisoned by a previous panic. | | `ErrConfig` | A configuration file or value was invalid or could not be applied. | | `ErrParseFailed` | The tree-sitter parser returned no tree for the given source input. | | `ErrParseTimeout` | The parse was cancelled because it exceeded its configured wall-clock budget. Raised only when a budget is configured — see `ProcessConfig.parse_timeout_ms`, which defaults to `nil`. | | `ErrQueryError` | A tree-sitter query could not be compiled or executed. | | `ErrInvalidRange` | A byte range was invalid (e.g., end before start, or out of bounds). | | `ErrDownload` | A parser download from GitHub releases failed. | | `ErrChecksumMismatch` | The downloaded file’s SHA-256 digest did not match the manifest’s expected value. | | `ErrCacheLock` | The cross-process download cache lock file could not be acquired or created. | *** # Java API Reference ## Java API Reference v1.16.1 [Section titled “Java API Reference v1.16.1”](#java-api-reference-v1161) ### Functions [Section titled “Functions”](#functions) #### detectLanguageFromExtension() [Section titled “detectLanguageFromExtension()”](#detectlanguagefromextension) Detect language name from a file extension (without leading dot). Returns `null` for unrecognized extensions. The match is case-insensitive. **Signature:** ```java public static @Nullable String detectLanguageFromExtension(String ext) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = detectLanguageFromExtension("value"); ``` **Parameters:** | Name | Type | Required | Description | | ----- | -------- | -------- | ----------- | | `ext` | `String` | Yes | The ext | **Returns:** `@Nullable String` *** #### detectLanguageFromPath() [Section titled “detectLanguageFromPath()”](#detectlanguagefrompath) Detect language name from a file path. Extracts the file extension and looks it up. Returns `null` if the path has no extension or the extension is not recognized. **Signature:** ```java public static @Nullable String detectLanguageFromPath(String path) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = detectLanguageFromPath("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `path` | `String` | Yes | Path to the file | **Returns:** `@Nullable String` *** #### detectLanguageFromContent() [Section titled “detectLanguageFromContent()”](#detectlanguagefromcontent) Detect language name from file content using the shebang line (`#!`). Inspects only the first line of `content`. If it begins with `#!`, the interpreter name is extracted and mapped to a language name. Handles common patterns: * `#!/usr/bin/env python3` → `"python"` * `#!/bin/bash` → `"bash"` * `#!/usr/bin/env node` → `"javascript"` The `-S` flag accepted by some `env` implementations is skipped automatically. Version suffixes (e.g. `python3.11`, `ruby3.2`) are stripped before matching. A leading UTF-8 BOM (`U+FEFF`) is skipped before the `#!` check, so a BOM-prefixed script is still detected by its shebang. Returns `null` when content does not start with `#!` (after stripping a leading BOM), the shebang is malformed, or the interpreter is not recognised. **Signature:** ```java public static @Nullable String detectLanguageFromContent(String content) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = detectLanguageFromContent("value"); ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ---------------------- | | `content` | `String` | Yes | The content to process | **Returns:** `@Nullable String` *** #### getHighlightsQuery() [Section titled “getHighlightsQuery()”](#gethighlightsquery) Get the highlights query for a language, if bundled. Returns the contents of `highlights.scm` as a static string, or `null` if no highlights query is bundled for this language. **Signature:** ```java public static @Nullable String getHighlightsQuery(String language) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = getHighlightsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `@Nullable String` *** #### getInjectionsQuery() [Section titled “getInjectionsQuery()”](#getinjectionsquery) Get the injections query for a language, if bundled. Returns the contents of `injections.scm` as a static string, or `null` if no injections query is bundled for this language. **Signature:** ```java public static @Nullable String getInjectionsQuery(String language) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = getInjectionsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `@Nullable String` *** #### getLocalsQuery() [Section titled “getLocalsQuery()”](#getlocalsquery) Get the locals query for a language, if bundled. Returns the contents of `locals.scm` as a static string, or `null` if no locals query is bundled for this language. **Signature:** ```java public static @Nullable String getLocalsQuery(String language) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = getLocalsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `@Nullable String` *** #### getTagsQuery() [Section titled “getTagsQuery()”](#gettagsquery) Get the tags query for a language, if bundled. Returns the contents of `tags.scm` as a static string, or `null` if no tags query is bundled for this language. **Signature:** ```java public static @Nullable String getTagsQuery(String language) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = getTagsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `@Nullable String` *** #### getIndentsQuery() [Section titled “getIndentsQuery()”](#getindentsquery) Get the indents query for a language, if bundled. Returns the contents of `indents.scm` (used for auto-indentation) as a static string, or `null` if no indents query is bundled for this language. **Signature:** ```java public static @Nullable String getIndentsQuery(String language) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = getIndentsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `@Nullable String` *** #### getFoldsQuery() [Section titled “getFoldsQuery()”](#getfoldsquery) Get the folds query for a language, if bundled. Returns the contents of `folds.scm` (used for code folding) as a static string, or `null` if no folds query is bundled for this language. **Signature:** ```java public static @Nullable String getFoldsQuery(String language) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = getFoldsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `@Nullable String` *** #### getLanguage() [Section titled “getLanguage()”](#getlanguage) Get a tree-sitter `Language` by name using the global registry. Resolves language aliases (e.g., `"shell"` maps to `"bash"`). When the `download` feature is enabled (default), automatically downloads the parser from GitHub releases if not found locally. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.Download` if auto-download fails. **Signature:** ```java public static Language getLanguage(String name) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = getLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Language` **Errors:** Throws `TreeSitterLanguagePackRsException`. *** #### getParser() [Section titled “getParser()”](#getparser) Get a `Parser` pre-configured for the given language. This is a convenience function that calls `get_language` and configures a new parser in one step. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language cannot be applied to the parser. **Signature:** ```java public static Parser getParser(String name) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = getParser("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Parser` **Errors:** Throws `TreeSitterLanguagePackRsException`. *** #### detectLanguage() [Section titled “detectLanguage()”](#detectlanguage) Detect language name from a file path or extension. This compatibility alias matches the pre-Alef Python binding API. **Signature:** ```java public static @Nullable String detectLanguage(String path) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = detectLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `path` | `String` | Yes | Path to the file | **Returns:** `@Nullable String` *** #### availableLanguages() [Section titled “availableLanguages()”](#availablelanguages) List all available language names (sorted, deduplicated, includes aliases). Returns names of both statically compiled and dynamically loadable languages, plus any configured aliases. **Signature:** ```java public static List availableLanguages() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = availableLanguages(); ``` **Returns:** `List` *** #### hasLanguage() [Section titled “hasLanguage()”](#haslanguage) Check if a language is available by name or alias. Returns `true` if the language can be loaded (statically compiled, dynamically available, or a known alias for one of these). **Signature:** ```java public static boolean hasLanguage(String name) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = hasLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `boolean` *** #### languageCount() [Section titled “languageCount()”](#languagecount) Return the number of available languages. Includes statically compiled languages, dynamically loadable languages, and aliases. **Signature:** ```java public static long languageCount() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = languageCount(); ``` **Returns:** `long` *** #### process() [Section titled “process()”](#process) Process source code and extract file intelligence using the global registry. Parses the source with tree-sitter and extracts metrics, structure, imports, exports, comments, docstrings, symbols, diagnostics, and/or chunks based on the flags set in `ProcessConfig`. **Errors:** Returns `Error.InvalidRange` if the config carries a zero-valued limit or the source exceeds `ProcessConfig.max_source_bytes`, `Error.ParseTimeout` if the parse exceeds `ProcessConfig.parse_timeout_ms`, `Error.LanguageNotFound` if the language is unknown, or `Error.ParseFailed` if parsing yields no tree. **Signature:** ```java public static ProcessResult process(String source, ProcessConfig config) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = process("value", new ProcessConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `String` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Throws `TreeSitterLanguagePackRsException`. *** #### init() [Section titled “init()”](#init) Initialize the language pack with the given configuration. Applies any custom cache directory, then downloads all languages and groups specified in the config. This is the recommended entry point when you want to pre-warm the cache before use. **Errors:** Returns an error if configuration cannot be applied or if downloads fail. **Signature:** ```java public static void init(PackConfig config) throws TreeSitterLanguagePackRsException ``` **Example:** ```java init(new PackConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Throws `TreeSitterLanguagePackRsException`. *** #### configure() [Section titled “configure()”](#configure) Apply download configuration without downloading anything. Use this to set a custom cache directory before the first call to `get_language` or any download function. Changing the cache dir after languages have been registered has no effect on already-loaded languages. `PackConfig.cache_dir` is a BASE directory, not the final libs path: this crate appends `tree-sitter-language-pack/v{version}/libs` to it, the same suffix applied to the platform default cache directory. In the example below, files actually land under `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`, never directly in `/tmp/my-parsers/`. Call `cache_dir` to read back the resolved, fully-suffixed path. **Errors:** Returns an error if the lock cannot be acquired. **Signature:** ```java public static void configure(PackConfig config) throws TreeSitterLanguagePackRsException ``` **Example:** ```java configure(new PackConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Throws `TreeSitterLanguagePackRsException`. *** #### download() [Section titled “download()”](#download) Download specific languages to the local cache. Returns the number of distinct languages available after the call. Already compiled or cached languages are included in the count. Aliases are resolved before counting, so `["shell", "bash"]` names one language and returns 1. **Errors:** Returns an error if any language is not available in the manifest or if the download fails. **Signature:** ```java public static long download(List names) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = download(List.of()); ``` **Parameters:** | Name | Type | Required | Description | | ------- | -------------- | -------- | ----------- | | `names` | `List` | Yes | The names | **Returns:** `long` **Errors:** Throws `TreeSitterLanguagePackRsException`. *** #### prefetch() [Section titled “prefetch()”](#prefetch) Prefetch grammars: download any not already loadable from disk, then load every requested language into the process registry so a subsequent hot loop only parses. Unlike `download()`, this does not trust in-memory availability — it downloads whenever a grammar is not actually loadable from disk (fixing the case where a known-but-not-downloaded grammar is reported present), then resolves and caches every requested language. Call it once, up front, before a parallel workload. **Errors:** Returns `Error.Download` if a required grammar cannot be fetched, or `Error.LanguageNotFound` if a requested name is unknown. **Signature:** ```java public static void prefetch(List languages) throws TreeSitterLanguagePackRsException ``` **Example:** ```java prefetch(List.of()); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | -------------- | -------- | ------------- | | `languages` | `List` | Yes | The languages | **Returns:** No return value. **Errors:** Throws `TreeSitterLanguagePackRsException`. *** #### downloadAll() [Section titled “downloadAll()”](#downloadall) Download all available languages from the remote manifest. Downloads the platform bundle and extracts every library it contains. Languages that appear in the manifest but are absent from the bundle (e.g. grammars that failed to compile at release time) are silently skipped — they are not treated as an error. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns an error if the manifest cannot be fetched or the bundle download fails. **Signature:** ```java public static long downloadAll() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = downloadAll(); ``` **Returns:** `long` **Errors:** Throws `TreeSitterLanguagePackRsException`. *** #### downloadGroup() [Section titled “downloadGroup()”](#downloadgroup) Download every language in a named group. Groups are defined by the remote manifest, not by this library, and let you ensure a curated set of related grammars in one call instead of listing each name to `download()`. Already-cached languages are skipped. Call `manifest_groups` to discover the group names the manifest actually defines. The published manifest currently defines a single group, `"all"`; earlier revisions of this documentation advertised `"web"`, `"data"`, and `"systems"`, which the manifest has never contained, so every call following that example failed. Do not hardcode a group name without checking. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns `Error.Download` if the manifest cannot be fetched, if the group is unknown — the message lists the groups the manifest defines — or if any constituent language fails to download. **Signature:** ```java public static long downloadGroup(String name) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = downloadGroup("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `long` **Errors:** Throws `TreeSitterLanguagePackRsException`. *** #### manifestLanguages() [Section titled “manifestLanguages()”](#manifestlanguages) Return all language names available in the remote manifest (371). Fetches (and caches) the remote manifest to discover the full list of downloadable languages. Use `downloaded_languages` to list what is already cached locally. **Errors:** Returns an error if the manifest cannot be fetched. **Signature:** ```java public static List manifestLanguages() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = manifestLanguages(); ``` **Returns:** `List` **Errors:** Throws `TreeSitterLanguagePackRsException`. *** #### manifestGroups() [Section titled “manifestGroups()”](#manifestgroups) Return the names of every language group the remote manifest defines, sorted. Group names are manifest data, not a compile-time constant of this library, so this is the only reliable way to learn what `download_group` and `PackConfig.groups` accept. The published manifest currently defines just `"all"`. **Errors:** Returns `Error.Download` if the manifest cannot be fetched. **Signature:** ```java public static List manifestGroups() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = manifestGroups(); ``` **Returns:** `List` **Errors:** Throws `TreeSitterLanguagePackRsException`. *** #### downloadedLanguages() [Section titled “downloadedLanguages()”](#downloadedlanguages) Return languages that are already downloaded and cached locally. Does not perform any network requests. Returns an empty list if the cache directory does not exist or cannot be read. **Signature:** ```java public static List downloadedLanguages() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = downloadedLanguages(); ``` **Returns:** `List` *** #### cleanCache() [Section titled “cleanCache()”](#cleancache) Delete all cached parser shared libraries. Resets the cache registration so the next call to `get_language` or a download function will re-register the (now empty) cache directory. **Errors:** Returns an error if the cache directory cannot be removed. **Signature:** ```java public static void cleanCache() throws TreeSitterLanguagePackRsException ``` **Example:** ```java cleanCache(); ``` **Returns:** No return value. **Errors:** Throws `TreeSitterLanguagePackRsException`. *** #### cacheDir() [Section titled “cacheDir()”](#cachedir) Return the effective cache directory path. This is `{base}/tree-sitter-language-pack/v{version}/libs/`, where `{base}` is either the custom BASE directory set via `configure` / `init` (`PackConfig.cache_dir`) or the platform default cache directory — both are suffixed identically, so a custom `cache_dir` is never used as the final libs path. The default resolves to `~/.cache/tree-sitter-language-pack/v{version}/libs/` on a typical Unix system. **Errors:** Returns an error if no cache directory can be resolved: `version` is somehow invalid, or (with no custom `cache_dir` configured) the platform reports none and `TREE_SITTER_LANGUAGE_PACK_CACHE_DIR` is unset. This crate no longer falls back to the temporary directory for the latter case — see #101 H2. **Signature:** ```java public static String cacheDir() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = cacheDir(); ``` **Returns:** `String` **Errors:** Throws `TreeSitterLanguagePackRsException`. *** ### Types [Section titled “Types”](#types) #### ByteRange [Section titled “ByteRange”](#byterange) A byte range — start (inclusive) to end (exclusive). | Field | Type | Default | Description | | ------- | ------ | ------- | ---------------------------- | | `start` | `long` | — | Inclusive start byte offset. | | `end` | `long` | — | Exclusive end byte offset. | *** #### ChunkContext [Section titled “ChunkContext”](#chunkcontext) Metadata for a single chunk of source code. | Field | Type | Default | Description | | ---------------- | --------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String` | — | Language name used to parse this chunk. | | `chunkIndex` | `long` | — | Zero-indexed position of this chunk within the file’s chunk list. | | `totalChunks` | `long` | — | Total number of chunks the file was split into. | | `nodeTypes` | `List` | `Collections.emptyList()` | Tree-sitter node kinds that appear at the top level of this chunk. | | `contextPath` | `List` | `Collections.emptyList()` | Hierarchical path of enclosing structural items (e.g., `["MyClass", "my_method"]`). | | `symbolsDefined` | `List` | `Collections.emptyList()` | Names of symbols defined within this chunk. | | `comments` | `List` | `Collections.emptyList()` | Comments contained within this chunk. | | `docstrings` | `List` | `Collections.emptyList()` | Docstrings contained within this chunk. Populated only for Python — the same language for which `ProcessResult.docstrings` is populated, and by the same classifier. Always empty for every other language. | | `hasErrorNodes` | `boolean` | — | Whether this chunk contains any tree-sitter error nodes. | *** #### CodeChunk [Section titled “CodeChunk”](#codechunk) A chunk of source code with rich metadata. | Field | Type | Default | Description | | ----------- | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `content` | `String` | — | The raw source text of this chunk. | | `startByte` | `long` | — | Inclusive start byte offset of this chunk in the original source. | | `endByte` | `long` | — | Exclusive end byte offset of this chunk in the original source. | | `startLine` | `long` | — | Zero-indexed start line of this chunk. | | `endLine` | `long` | — | Zero-indexed row of the last byte actually included in this chunk (inclusive — the same row a `Span.end_line` would report for a node ending on that byte). Computed the same way regardless of whether the source has a trailing newline: it is always the row of `end_byte - 1`, never a phantom row past the file’s real content. | | `metadata` | `ChunkContext` | — | Contextual metadata about this chunk. | *** #### CommentInfo [Section titled “CommentInfo”](#commentinfo) A comment extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------------ | ------------------ | ----------------------------------------------------------------- | | `text` | `String` | — | The raw text content of the comment. | | `kind` | `CommentKind` | `CommentKind.Line` | The kind of comment (line, block, or doc). | | `span` | `Span` | — | Source span covering the comment. | | `associatedNode` | `@Nullable String` | `null` | Name of the syntax node this comment is directly associated with. | *** #### DataAttribute [Section titled “DataAttribute”](#dataattribute) An XML-style attribute attached to an `Element` node. Populated only for `DataNodeKind.Element`; always empty for `KeyValue` and `Sequence` nodes. | Field | Type | Default | Description | | ------- | -------- | ------- | --------------------------------------------------------------- | | `name` | `String` | — | Attribute name (e.g. `"class"`, `"href"`). | | `value` | `String` | — | Attribute value as a raw string (quotes stripped). | | `span` | `Span` | — | Source span covering the entire `name="value"` attribute token. | *** #### DataNode [Section titled “DataNode”](#datanode) A node in the hierarchical data tree produced by data-format extraction. When `ProcessConfig.data_extraction` is `true`, `ProcessResult.data` is populated with a root `DataNode` whose `children` mirror the structure of the parsed file. The `kind` field determines which other fields are meaningful: | `kind` | `key` | `value` | `attributes` | `children` | | ---------- | ------------------------- | ------------ | ------------ | -------------- | | `KeyValue` | key / mapping key / index | leaf value | empty | nested map | | `Element` | XML tag name | text content | XML attrs | child elements | | `Sequence` | positional index (`"0"`) | leaf value | empty | sub-items | | Field | Type | Default | Description | | ------------ | --------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------- | | `kind` | `DataNodeKind` | `DataNodeKind.KeyValue` | Whether this node is a key/value pair, XML element, or sequence item. | | `key` | `@Nullable String` | `null` | Key, attribute name, tag name, or positional index (`"0"`, `"1"`, …). `null` at the document root. | | `value` | `@Nullable String` | `null` | Leaf scalar value, if any. `null` for containers (objects, arrays, XML elements with child elements). | | `attributes` | `List` | `Collections.emptyList()` | Attributes on element-shape nodes (XML `STag` attributes). Empty for all other kinds. | | `children` | `List` | `Collections.emptyList()` | Children for nested containers and XML element bodies. | | `span` | `Span` | — | Source span covering this node in the original source file. | *** #### Diagnostic [Section titled “Diagnostic”](#diagnostic) A diagnostic (syntax error, missing node, etc.) from parsing. | Field | Type | Default | Description | | ---------- | -------------------- | -------------------------- | ---------------------------------------------- | | `message` | `String` | — | Human-readable description of the diagnostic. | | `severity` | `DiagnosticSeverity` | `DiagnosticSeverity.Error` | Severity of the diagnostic. | | `span` | `Span` | — | Source span where the diagnostic was detected. | *** #### DocSection [Section titled “DocSection”](#docsection) A section within a docstring (e.g., Args, Returns, Raises). | Field | Type | Default | Description | | ------------- | ------------------ | ------- | ------------------------------------------------------- | | `kind` | `String` | — | Section kind (e.g., `"args"`, `"returns"`, `"raises"`). | | `name` | `@Nullable String` | `null` | Parameter or return value name, if applicable. | | `description` | `String` | — | Description text for this section. | *** #### DocstringInfo [Section titled “DocstringInfo”](#docstringinfo) A docstring extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------------ | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | `String` | — | The raw text of the docstring. | | `format` | `DocstringFormat` | `DocstringFormat.PythonTripleQuote` | The docstring format (Python, JSDoc, Rustdoc, etc.). | | `span` | `Span` | — | Source span covering the docstring. | | `associatedItem` | `@Nullable String` | `null` | Name of the item this docstring documents. | | `parsedSections` | `List` | `Collections.emptyList()` | Parsed sections of the docstring (Args, Returns, Raises, etc.). **Reserved: not yet populated.** Always empty, for every `DocstringFormat`. Parsing a docstring body into sections requires implementing each convention’s own layout (Google/NumPy/reST style for Python, `@param`/`@returns` for JSDoc/Javadoc, and so on), which no extractor here does yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | *** #### DownloadManager [Section titled “DownloadManager”](#downloadmanager) Manages downloading and caching of pre-built parser shared libraries. ##### Methods [Section titled “Methods”](#methods) ###### create() [Section titled “create()”](#create) Create a new download manager for the given version. **Errors:** Returns `Error.Download` if `version` is empty, contains a path separator or `..`, or contains a character outside `[A-Za-z0-9.+-]` — see `validate_version` — or if no cache directory can be resolved (see `Self.default_cache_dir`). **Signature:** ```java public static DownloadManager create(String version) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = DownloadManager.create("value"); ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ----------- | | `version` | `String` | Yes | The version | **Returns:** `DownloadManager` **Errors:** Throws `TreeSitterLanguagePackRsException`. ###### installedLanguages() [Section titled “installedLanguages()”](#installedlanguages) List languages that are already downloaded and cached. Derived from the on-disk cache filenames, one canonical name per file, plus every alias that resolves to it (via `aliases_for`) — so this list agrees with the user-facing `LanguageRegistry.available_languages` about which names are “available”; both report `"shell"` once `bash` is cached, for example. A previous version reported canonical names only, which could never agree with `available_languages()`. See #107. Returns an empty list if the cache directory does not exist. If it exists but cannot be read (e.g. a permission error), also returns an empty list — changing this to a `Result` would be a breaking change across every language binding — but logs a `tracing.warn!` so the failure is not silently indistinguishable from “nothing installed”. **Signature:** ```java public List installedLanguages() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.installedLanguages(); ``` **Returns:** `List` ###### downloadAllBestEffort() [Section titled “downloadAllBestEffort()”](#downloadallbesteffort) Download the platform bundle and extract every library file it contains. Unlike `Self.ensure_languages`, this does not check the manifest language list against archive contents — it simply extracts all `.so`/`.dylib`/`.dll` files from the bundle. Languages in the manifest that are missing from the archive are silently ignored rather than returning an error. Returns the number of library files extracted (including those already cached). **Signature:** ```java public long downloadAllBestEffort() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.downloadAllBestEffort(); ``` **Returns:** `long` **Errors:** Throws `TreeSitterLanguagePackRsException`. ###### cleanCache() [Section titled “cleanCache()”](#cleancache-1) Remove all cached parser libraries. Acquires the cross-process lock so `clean_cache` cannot race a concurrent downloader (avoids Windows sharing-violation errors against an in-flight bundle write). The `.download.lock` file itself is **not** removed — it is permanent infrastructure; deleting it could allow a concurrent process that already opened the file to continue holding a stale lock handle while a new process opens a fresh inode, breaking the mutual-exclusion guarantee. **Signature:** ```java public void cleanCache() throws TreeSitterLanguagePackRsException ``` **Example:** ```java instance.cleanCache(); ``` **Returns:** No return value. **Errors:** Throws `TreeSitterLanguagePackRsException`. ###### close() [Section titled “close()”](#close) Releases the native handle backing this instance. Implements `AutoCloseable`; safe to call more than once. **Signature:** ```java public void close() throws TreeSitterLanguagePackRsException ``` **Example:** ```java instance.close(); ``` **Returns:** No return value. *** #### ExportInfo [Section titled “ExportInfo”](#exportinfo) An export statement extracted from source code. | Field | Type | Default | Description | | ------ | ------------ | ------------------ | -------------------------------------------------- | | `name` | `String` | — | The exported name. | | `kind` | `ExportKind` | `ExportKind.Named` | The kind of export (named, default, or re-export). | | `span` | `Span` | — | Source span covering the export statement. | *** #### FileMetrics [Section titled “FileMetrics”](#filemetrics) Aggregate metrics for a source file. | Field | Type | Default | Description | | -------------- | ------ | ------- | -------------------------------------------------------------- | | `totalLines` | `long` | — | Total number of lines (including blank and comment lines). | | `codeLines` | `long` | — | Number of lines containing non-blank, non-comment source code. | | `commentLines` | `long` | — | Number of lines that are entirely comments. | | `blankLines` | `long` | — | Number of blank (whitespace-only) lines. | | `totalBytes` | `long` | — | Total byte length of the source file. | | `nodeCount` | `long` | — | Total number of nodes in the syntax tree. | | `errorCount` | `long` | — | Number of error nodes in the syntax tree (parse errors). | | `maxDepth` | `long` | — | Maximum nesting depth reached in the syntax tree. | *** #### ImportInfo [Section titled “ImportInfo”](#importinfo) An import statement extracted from source code. | Field | Type | Default | Description | | ------------ | ------------------ | ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `source` | `String` | — | The module or path being imported from. | | `items` | `List` | `Collections.emptyList()` | Specific names imported from the source module. For `import a, b` / `from m import a, b`, every entry’s base name (never the alias). For a JavaScript/TypeScript named-imports clause (`import { a, b as c } from 'm'`), every specifier’s original name. Populated for Python and JavaScript/TypeScript only. Always empty for every other language this library recognises import statements for — Rust, Go, Java, Kotlin, and Elixir (`import`/`alias`/`require`/`use`) — and for a JS/TS namespace import (`import * as ns`) or default import (`import x from 'm'`), neither of which names individual items. | | `alias` | `@Nullable String` | `null` | Alias assigned to the import (e.g., `import numpy as np`). Populated for Python’s single-name form (`import numpy as np`, `from m import a as b`) and JavaScript/TypeScript’s namespace form (`import * as ns from 'm'`) or a named-imports clause naming exactly one specifier (`import { a as b } from 'm'`). `null` for Rust, Go, Java, Kotlin, and Elixir (which has its own `as:` alias option on `alias` directives, not yet extracted here) — and for a Python statement that aliases several names at once (`import os, sys as s`), where there is no single alias to report for the statement as a whole, so only `items` is populated for it. | | `isWildcard` | `boolean` | — | Whether this is a wildcard import (e.g., `import *` or `use foo.*`). Detected from the syntax tree — a dedicated wildcard node (`wildcard_import` in Python, `use_wildcard` in Rust) or a bare `*` token outside of string-literal content — not by searching the import’s source text for a `*` character, so a glob in an import path string (`import a from './glob*.js'`) is not mistaken for one. | | `span` | `Span` | — | Source span covering the import statement. | *** #### Language [Section titled “Language”](#language) ##### Methods [Section titled “Methods”](#methods-1) ###### close() [Section titled “close()”](#close-1) Releases the native handle backing this instance. Implements `AutoCloseable`; safe to call more than once. **Signature:** ```java public void close() throws TreeSitterLanguagePackRsException ``` **Example:** ```java instance.close(); ``` **Returns:** No return value. *** #### LanguageRegistry [Section titled “LanguageRegistry”](#languageregistry) Thread-safe registry of tree-sitter language parsers. Manages both statically compiled and dynamically loaded language grammars. Use `LanguageRegistry.new()` for the default registry, or access the global instance via the module-level convenience functions (`get_language`, `available_languages`, etc.). ##### Methods [Section titled “Methods”](#methods-2) ###### create() [Section titled “create()”](#create-1) Create a new registry populated with all statically compiled languages. When the `dynamic-loading` feature is enabled, the registry also knows about dynamically loadable grammars and will load them on demand. **Signature:** ```java public static LanguageRegistry create() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = LanguageRegistry.create(); ``` **Returns:** `LanguageRegistry` ###### getLanguage() [Section titled “getLanguage()”](#getlanguage-1) Get a tree-sitter `Language` by name. Resolves aliases (e.g., `"shell"` -> `"bash"`, `"makefile"` -> `"make"`), then looks up the language in the static table. When the `dynamic-loading` feature is enabled, falls back to loading a shared library on demand. **Errors:** Returns `Error.LanguageNotFound` if the name (after alias resolution) does not match any known grammar. **Signature:** ```java public Language getLanguage(String name) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.getLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Language` **Errors:** Throws `TreeSitterLanguagePackRsException`. ###### availableLanguages() [Section titled “availableLanguages()”](#availablelanguages-1) List all available language names, sorted and deduplicated. Includes statically compiled languages, dynamically loadable languages (if the `dynamic-loading` feature is enabled), and all configured aliases. **Signature:** ```java public List availableLanguages() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.availableLanguages(); ``` **Returns:** `List` ###### hasParser() [Section titled “hasParser()”](#hasparser) Check whether this language can be parsed right now, without downloading. Resolves aliases, then answers from exactly the lookup `get_language` performs: the statically compiled table, the already-loaded dynamic grammars, and the parser shared libraries present in the primary and extra (download-cache) library directories. It never performs network I/O. A previous implementation consulted only the statically compiled table. That table is empty in every build that does not set `TSLP_LANGUAGES`, so the function answered `false` for languages this registry parses perfectly well. Contrast `has_language`, which is also `true` for a grammar that is merely *known to the manifest* and would have to be downloaded first. The pair distinguishes “we can parse it offline, now” from “we recognise the name”. The first `true` answer for a dynamic grammar loads its shared library: loading is the only way to know the grammar is usable, since a truncated or wrong-architecture library exists on disk but cannot parse. Loads are cached process-wide, so repeat calls are cheap. **Signature:** ```java public boolean hasParser(String name) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.hasParser("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `boolean` ###### hasLanguage() [Section titled “hasLanguage()”](#haslanguage-1) Check whether a language is available by name or alias. Returns `true` if the language can be loaded, either from the static table or from a dynamic library on disk. Every branch is one more way to answer `true`, so they are ordered cheapest-first and the filesystem is only consulted once every in-memory source has said no. Probing the loaded-grammar map and the manifest ahead of the `stat` calls is what keeps this off the syscall path for the languages a process actually uses. **Signature:** ```java public boolean hasLanguage(String name) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.hasLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `boolean` ###### languageCount() [Section titled “languageCount()”](#languagecount-1) Return the total number of available languages (including aliases). Counts the same set `available_languages` lists, without materialising or sorting it. **Signature:** ```java public long languageCount() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.languageCount(); ``` **Returns:** `long` ###### process() [Section titled “process()”](#process-1) Parse source code and extract file intelligence based on config in a single pass. **Errors:** Returns `Error.InvalidRange` if the config is invalid (see `ProcessConfig.validate`) or if the source exceeds the configured `max_source_bytes`; `Error.LanguageNotFound` if the language is unknown; or `Error.ParseFailed` if parsing produces no tree. **Signature:** ```java public ProcessResult process(String source, ProcessConfig config) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.process("value", new ProcessConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `String` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Throws `TreeSitterLanguagePackRsException`. ###### close() [Section titled “close()”](#close-2) Releases the native handle backing this instance. Implements `AutoCloseable`; safe to call more than once. **Signature:** ```java public void close() throws TreeSitterLanguagePackRsException ``` **Example:** ```java instance.close(); ``` **Returns:** No return value. *** #### Node [Section titled “Node”](#node) A single syntax node within a `Tree`. Nodes hold a strong reference to their parent tree so they remain valid regardless of how the tree is moved or stored at the FFI boundary. ##### Methods [Section titled “Methods”](#methods-3) ###### kind() [Section titled “kind()”](#kind) Return the node’s kind name (e.g. `"function_definition"`). **Signature:** ```java public String kind() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.kind(); ``` **Returns:** `String` ###### kindId() [Section titled “kindId()”](#kindid) Return the node’s numeric kind ID. Tree-sitter assigns a stable `u16` ID to every node kind in a grammar (e.g. `"function_definition" → 42`). Comparing `kind_id()` is cheaper than comparing the string `kind()` in tight AST loops. **Signature:** ```java public short kindId() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.kindId(); ``` **Returns:** `short` ###### startByte() [Section titled “startByte()”](#startbyte) Return the inclusive start byte offset of this node. **Signature:** ```java public long startByte() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.startByte(); ``` **Returns:** `long` ###### endByte() [Section titled “endByte()”](#endbyte) Return the exclusive end byte offset of this node. **Signature:** ```java public long endByte() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.endByte(); ``` **Returns:** `long` ###### byteRange() [Section titled “byteRange()”](#byterange-1) Return the node’s byte range as a `ByteRange`. Callers should slice their own source bytes — this is a zero-copy text accessor. **Signature:** ```java public ByteRange byteRange() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.byteRange(); ``` **Returns:** `ByteRange` ###### startPosition() [Section titled “startPosition()”](#startposition) Return the start `Point` (row, column). **Signature:** ```java public Point startPosition() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.startPosition(); ``` **Returns:** `Point` ###### endPosition() [Section titled “endPosition()”](#endposition) Return the end `Point` (row, column). **Signature:** ```java public Point endPosition() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.endPosition(); ``` **Returns:** `Point` ###### isNamed() [Section titled “isNamed()”](#isnamed) True when this node is named (not punctuation/whitespace). **Signature:** ```java public boolean isNamed() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.isNamed(); ``` **Returns:** `boolean` ###### isError() [Section titled “isError()”](#iserror) True when this is an error node. **Signature:** ```java public boolean isError() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.isError(); ``` **Returns:** `boolean` ###### isMissing() [Section titled “isMissing()”](#ismissing) True when this is a missing-token node. **Signature:** ```java public boolean isMissing() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.isMissing(); ``` **Returns:** `boolean` ###### isExtra() [Section titled “isExtra()”](#isextra) True when this is an “extra” node (e.g. a comment). **Signature:** ```java public boolean isExtra() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.isExtra(); ``` **Returns:** `boolean` ###### hasError() [Section titled “hasError()”](#haserror) True when this node or any descendant is an error. **Signature:** ```java public boolean hasError() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.hasError(); ``` **Returns:** `boolean` ###### parent() [Section titled “parent()”](#parent) Return this node’s parent, if any. **Signature:** ```java public @Nullable Node parent() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.parent(); ``` **Returns:** `@Nullable Node` ###### child() [Section titled “child()”](#child) Return the i-th child of this node, if any. **Signature:** ```java public @Nullable Node child(int index) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.child(42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | ----- | -------- | ----------- | | `index` | `int` | Yes | The index | **Returns:** `@Nullable Node` ###### childCount() [Section titled “childCount()”](#childcount) Total number of children (including unnamed). **Signature:** ```java public long childCount() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.childCount(); ``` **Returns:** `long` ###### namedChild() [Section titled “namedChild()”](#namedchild) Return the i-th named child of this node, if any. **Signature:** ```java public @Nullable Node namedChild(int index) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.namedChild(42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | ----- | -------- | ----------- | | `index` | `int` | Yes | The index | **Returns:** `@Nullable Node` ###### namedChildCount() [Section titled “namedChildCount()”](#namedchildcount) Number of named children of this node. **Signature:** ```java public long namedChildCount() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.namedChildCount(); ``` **Returns:** `long` ###### childByFieldName() [Section titled “childByFieldName()”](#childbyfieldname) Look up a child by its grammar-defined field name. **Signature:** ```java public @Nullable Node childByFieldName(String name) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.childByFieldName("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `@Nullable Node` ###### toSexp() [Section titled “toSexp()”](#tosexp) Return the S-expression form of this node’s subtree. **Signature:** ```java public String toSexp() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.toSexp(); ``` **Returns:** `String` ###### walk() [Section titled “walk()”](#walk) Return a `TreeCursor` positioned at this node. **Signature:** ```java public TreeCursor walk() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.walk(); ``` **Returns:** `TreeCursor` ###### close() [Section titled “close()”](#close-3) Releases the native handle backing this instance. Implements `AutoCloseable`; safe to call more than once. **Signature:** ```java public void close() throws TreeSitterLanguagePackRsException ``` **Example:** ```java instance.close(); ``` **Returns:** No return value. *** #### PackConfig [Section titled “PackConfig”](#packconfig) Configuration for the tree-sitter language pack. Controls cache directory and which languages to pre-download. Can be loaded from a TOML file, constructed programmatically, or passed as a dict/object from language bindings. | Field | Type | Default | Description | | ----------- | ------------------------ | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cacheDir` | `@Nullable String` | `null` | Override the BASE directory the parser cache lives under. This is a base, not the final library path: the crate appends `tree-sitter-language-pack/v{version}/libs` to it, exactly as it does to the platform default. So `cache_dir = "/tmp/my-parsers"` resolves to `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`. The suffix is not cosmetic. It keeps the whole cache tree — manifest, bundles and lock file included — inside a directory this library owns and versions. Earlier releases used this path verbatim, which put those files in the configured directory’s PARENT and let a cache built by one crate version be reused by another. Default base: the platform cache dir, e.g. `~/.cache` on Linux. | | `languages` | `@Nullable List` | `Collections.emptyList()` | Languages to pre-download on init. Each entry is a language name (e.g. `"python"`, `"rust"`). | | `groups` | `@Nullable List` | `Collections.emptyList()` | Language groups to pre-download. Group names come from the remote manifest, so the valid set is not fixed by this library; the published manifest currently defines only `"all"`. Call `manifest_groups` to enumerate them. An unknown name makes `init` fail. | *** #### Parser [Section titled “Parser”](#parser) A tree-sitter parser configured for one language at a time. ##### Methods [Section titled “Methods”](#methods-4) ###### create() [Section titled “create()”](#create-2) Construct a new parser with no language set and no parse limits. Call `Parser.set_language` before parsing. Limits are opt-in via `set_max_source_bytes` and `set_parse_timeout_ms`; both default to unbounded so that existing callers are unaffected. **Signature:** ```java public static Parser create() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = Parser.create(); ``` **Returns:** `Parser` ###### setMaxSourceBytes() [Section titled “setMaxSourceBytes()”](#setmaxsourcebytes) Refuse to parse sources longer than `max_bytes`. `null` (the default) means no limit. Over-limit input makes `parse` and `parse_bytes` return `null` after emitting a `WARN`; input is never silently truncated. See `RECOMMENDED_MAX_SOURCE_BYTES`. **Signature:** ```java public void setMaxSourceBytes(long maxBytes) throws TreeSitterLanguagePackRsException ``` **Example:** ```java instance.setMaxSourceBytes(42); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ---------------- | -------- | ------------- | | `maxBytes` | `@Nullable Long` | No | The max bytes | **Returns:** No return value. ###### setParseTimeoutMs() [Section titled “setParseTimeoutMs()”](#setparsetimeoutms) Cancel a parse that exceeds `timeout_ms` milliseconds of wall clock. `null` (the default) means no budget. Cancellation runs through tree-sitter’s parse progress callback, so it is granular to that callback’s interval rather than exact. See `RECOMMENDED_PARSE_TIMEOUT_MS`. **Signature:** ```java public void setParseTimeoutMs(long timeoutMs) throws TreeSitterLanguagePackRsException ``` **Example:** ```java instance.setParseTimeoutMs(42); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | ---------------- | -------- | -------------- | | `timeoutMs` | `@Nullable Long` | No | The timeout ms | **Returns:** No return value. ###### setLanguage() [Section titled “setLanguage()”](#setlanguage) Configure the parser to use the language identified by name (e.g. `"python"`). Resolves the language through the global registry — auto-downloading if necessary, when the `download` feature is enabled. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language ABI is incompatible. **Signature:** ```java public void setLanguage(String name) throws TreeSitterLanguagePackRsException ``` **Example:** ```java instance.setLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** No return value. **Errors:** Throws `TreeSitterLanguagePackRsException`. ###### parse() [Section titled “parse()”](#parse) Parse a UTF-8 source string. Returns `null` if no language is set, if the parse was cancelled by the configured timeout, or if the source exceeds the configured size limit. Each non-parse outcome is logged, so an empty result is never silent. ###### Concurrency [Section titled “Concurrency”](#concurrency) Parsing runs fully in parallel across threads for almost every language — no lock is taken. The exception is the small set of grammars whose external scanner keeps mutable process-global state (currently just `properties`): parses of that language are serialized against each other through an internal per-language lock, so that concurrent threads can’t corrupt shared scanner state. Every other language is unaffected by that lock and never waits on it. **Signature:** ```java public @Nullable Tree parse(String source) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.parse("value"); ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------- | -------- | ----------- | | `source` | `String` | Yes | The source | **Returns:** `@Nullable Tree` ###### parseBytes() [Section titled “parseBytes()”](#parsebytes) Parse a raw byte slice. Same outcomes as `parse`, including the concurrency behaviour documented there. **Signature:** ```java public @Nullable Tree parseBytes(byte[] source) throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.parseBytes("data".getBytes()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ---------- | -------- | ----------- | | `source` | `byte\[\]` | Yes | The source | **Returns:** `@Nullable Tree` ###### reset() [Section titled “reset()”](#reset) Reset internal state. The next call to `parse` will not be incremental. **Signature:** ```java public void reset() throws TreeSitterLanguagePackRsException ``` **Example:** ```java instance.reset(); ``` **Returns:** No return value. ###### close() [Section titled “close()”](#close-4) Releases the native handle backing this instance. Implements `AutoCloseable`; safe to call more than once. **Signature:** ```java public void close() throws TreeSitterLanguagePackRsException ``` **Example:** ```java instance.close(); ``` **Returns:** No return value. *** #### Point [Section titled “Point”](#point) A source position — row + column, zero-indexed. | Field | Type | Default | Description | | -------- | ------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `row` | `long` | — | Zero-indexed row number. | | `column` | `long` | — | Zero-indexed column, counted in **bytes** from the start of the row. This is `tree_sitter.Point.column` verbatim, and tree-sitter defines it as a byte offset — not characters, and not UTF-16 code units. Measured on a row of the form `x = ''` where `` is a single 4-byte character (an emoji), the string node reports columns `4..10`, identical to its byte range; the character columns would be `4..7` and the UTF-16 columns `4..8`. Anything that builds LSP positions (UTF-16) or editor caret columns (characters) from this field is silently wrong on every row containing a non-ASCII byte, and must re-measure the row against the source text instead. Earlier releases documented this field as UTF-16 code units; that was never what the value contained. | *** #### ProcessConfig [Section titled “ProcessConfig”](#processconfig) Configuration for the `process()` function. Controls which analysis features are enabled and whether chunking is performed. | Field | Type | Default | Description | | ---------------- | ---------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String` | `""` | Language name (required). | | `structure` | `boolean` | `true` | Extract structural items (functions, classes, etc.). Default: true. | | `imports` | `boolean` | `true` | Extract import statements. Default: true. | | `exports` | `boolean` | `true` | Extract export statements. Default: true. | | `comments` | `boolean` | `false` | Extract comments. Default: false. | | `docstrings` | `boolean` | `false` | Extract docstrings. Default: false. | | `symbols` | `boolean` | `false` | Extract symbol definitions. Default: false. | | `diagnostics` | `boolean` | `false` | Include parse diagnostics. Default: false. | | `chunkMaxSize` | `@Nullable Long` | `null` | Maximum chunk size in bytes. `null` disables chunking. `Some(0)` is rejected by `ProcessConfig.validate` with `Error.InvalidRange`. A zero-sized chunk limit previously produced an empty chunk list and silently discarded the whole source; use `null` to mean “do not chunk”. | | `dataExtraction` | `boolean` | `false` | Extract hierarchical key/value data tree from data-format files. Default: false. When `true`, `ProcessResult.data` is populated with a `DataNode` tree for supported languages: JSON, YAML, TOML, `.properties`, HCL/HOCON, INI, editorconfig, KDL, CUE, CSV, PSV, PO, nginx config, Caddy config, XML, and DTD. For languages outside this set the field is left as `null`. | | `maxSourceBytes` | `@Nullable Long` | `null` | Reject source longer than this many bytes instead of parsing it. Default: `null` (unbounded). Tree-sitter allocates and walks proportionally to input size, so an unbounded parse of attacker-supplied input is a denial-of-service vector. The default stays unbounded for backward compatibility; services handling untrusted input should opt in, e.g. with `RECOMMENDED_MAX_SOURCE_BYTES`. Exceeding the limit fails the call with `Error.InvalidRange` — the source is never silently truncated. | | `parseTimeoutMs` | `@Nullable Long` | `null` | Wall-clock budget for the parse step, in milliseconds. Default: `null` (no timeout). Enforced through tree-sitter’s parse progress callback, which the parser invokes periodically; cancellation is therefore granular to that callback interval rather than exact. A parse that exceeds the budget fails with `Error.ParseTimeout`. | *** #### ProcessResult [Section titled “ProcessResult”](#processresult) Complete analysis result from processing a source file. Contains metrics, structural analysis, imports/exports, comments, docstrings, symbols, diagnostics, and optionally chunked code segments. Fields are populated based on the `ProcessConfig` flags. | Field | Type | Default | Description | | ------------- | --------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String` | — | The language name used to parse the source file. | | `metrics` | `FileMetrics` | — | File-level metrics (line counts, byte size, error count). | | `structure` | `List` | `Collections.emptyList()` | Top-level structural items (functions, classes, etc.). | | `imports` | `List` | `Collections.emptyList()` | Import statements extracted from the source. | | `exports` | `List` | `Collections.emptyList()` | Export statements extracted from the source. | | `comments` | `List` | `Collections.emptyList()` | Comments extracted from the source. | | `docstrings` | `List` | `Collections.emptyList()` | Docstrings extracted from the source. | | `symbols` | `List` | `Collections.emptyList()` | Symbol definitions (variables, types, functions) extracted from the source. | | `diagnostics` | `List` | `Collections.emptyList()` | Parse diagnostics (syntax errors, missing nodes) from tree-sitter. | | `chunks` | `List` | `Collections.emptyList()` | Syntax-aware code chunks produced when chunking is enabled. | | `data` | `@Nullable DataNode` | `null` | Hierarchical data tree extracted when `config.data_extraction` is `true`. Populated for supported data-format languages (JSON, YAML, TOML, properties, HCL, INI, XML, CSV, and more). `null` when `data_extraction` is `false` (the default) or when the language is not a recognised data format. See `DataNode` for the shape of the returned tree. | *** #### Span [Section titled “Span”](#span) Byte and line/column range in source code. Represents both byte offsets (for slicing) and human-readable line/column positions (for display and diagnostics). | Field | Type | Default | Description | | ------------- | ------ | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `startByte` | `long` | — | Inclusive start byte offset in the source. | | `endByte` | `long` | — | Exclusive end byte offset in the source. | | `startLine` | `long` | — | Zero-indexed line number of the span’s start. | | `startColumn` | `long` | — | Zero-indexed column of the span’s start, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | | `endLine` | `long` | — | Zero-indexed line number of the span’s end. | | `endColumn` | `long` | — | Zero-indexed column of the span’s end, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | *** #### StructureItem [Section titled “StructureItem”](#structureitem) A structural item (function, class, struct, etc.) in source code. | Field | Type | Default | Description | | ------------ | --------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `kind` | `StructureKind` | `StructureKind.Function` | The kind of structural item. | | `name` | `@Nullable String` | `null` | The declared name of the item, if present. | | `visibility` | `@Nullable String` | `null` | Visibility modifier (e.g., `"pub"`, `"public"`, `"private"`). | | `span` | `Span` | — | Source span covering the entire item declaration. | | `children` | `List` | `Collections.emptyList()` | Nested structural items (e.g., methods within a class). | | `decorators` | `List` | `Collections.emptyList()` | Decorator or attribute names applied to the item. **Reserved: not yet populated.** Always empty, for every language. Recognising a decorator requires per-language grammar knowledge (a Python `decorated_definition` wrapper, Java/C# annotations, Rust attributes each have a different shape), which no extractor here implements yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | | `docComment` | `@Nullable String` | `null` | Documentation comment attached to the item, if any. The text of the comment (or run of comments) immediately preceding the item, with no blank line in between, when that comment is classified as a doc comment. Multiple adjacent single-line doc comments (Rust `///`) are joined with `\n` in source order. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`). `null` for every other language, and for a preceding comment that is not in doc-comment form (a plain `#` comment in Python, Ruby, or Elixir) — Python’s docstring convention is captured separately, as `DocstringInfo`, not through this field. | | `signature` | `@Nullable String` | `null` | Full signature text of the item (e.g., function parameters and return type). The item’s own source text from its start up to the start of its body (see `StructureItem.body_span`), trimmed of trailing whitespace — for example `fn add(a: i32, b: i32) -> i32` for a Rust function whose body is `{ a + b }`. `null` only when that text is empty, which does not happen for any item `StructureKind` currently reports. Populated for every language and kind this library extracts structure for, since it is derived from `body_span`’s boundary rather than per-language syntax. | | `bodySpan` | `@Nullable Span` | `null` | Source span covering only the body of the item, if distinct from the declaration. | *** #### SymbolInfo [Section titled “SymbolInfo”](#symbolinfo) A symbol (variable, function, type, etc.) extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------------ | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `String` | — | The name of the symbol. | | `kind` | `SymbolKind` | `SymbolKind.Variable` | The kind of symbol (variable, function, class, etc.). | | `span` | `Span` | — | Source span covering the symbol definition. | | `typeAnnotation` | `@Nullable String` | `null` | Explicit type annotation, if present in the source. | | `doc` | `@Nullable String` | `null` | Documentation comment immediately preceding this symbol, resolved by the same walk `StructureItem.doc_comment` uses (see `doc_comment_at`) — never hard-coded `null`. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`) — the languages whose comment classification recognizes a doc-kind comment. `null` for every other language (e.g. Python, Go, Ruby, which have no doc-kind comment classification), and also `null` when a symbol in a supported language simply has no doc comment immediately above it. | *** #### Tree [Section titled “Tree”](#tree) A parsed syntax tree. Cheap to clone (refcount bump). ##### Methods [Section titled “Methods”](#methods-5) ###### rootNode() [Section titled “rootNode()”](#rootnode) Return the root `Node` of this tree. **Signature:** ```java public Node rootNode() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.rootNode(); ``` **Returns:** `Node` ###### walk() [Section titled “walk()”](#walk-1) Return a `TreeCursor` positioned at the root. **Signature:** ```java public TreeCursor walk() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.walk(); ``` **Returns:** `TreeCursor` ###### close() [Section titled “close()”](#close-5) Releases the native handle backing this instance. Implements `AutoCloseable`; safe to call more than once. **Signature:** ```java public void close() throws TreeSitterLanguagePackRsException ``` **Example:** ```java instance.close(); ``` **Returns:** No return value. *** #### TreeCursor [Section titled “TreeCursor”](#treecursor) A cursor for traversing a `Tree`. ##### Methods [Section titled “Methods”](#methods-6) ###### node() [Section titled “node()”](#node-1) Return the `Node` at the cursor’s current position. **Signature:** ```java public Node node() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.node(); ``` **Returns:** `Node` ###### gotoFirstChild() [Section titled “gotoFirstChild()”](#gotofirstchild) Move the cursor to the first child of the current node. Returns `true` if a child existed. **Signature:** ```java public boolean gotoFirstChild() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.gotoFirstChild(); ``` **Returns:** `boolean` ###### gotoParent() [Section titled “gotoParent()”](#gotoparent) Move the cursor to the parent of the current node. Returns `true` if a parent existed. **Signature:** ```java public boolean gotoParent() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.gotoParent(); ``` **Returns:** `boolean` ###### gotoNextSibling() [Section titled “gotoNextSibling()”](#gotonextsibling) Move the cursor to the next sibling of the current node. Returns `true` if a sibling existed. **Signature:** ```java public boolean gotoNextSibling() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.gotoNextSibling(); ``` **Returns:** `boolean` ###### fieldName() [Section titled “fieldName()”](#fieldname) Return the field name for the current node, if any. **Signature:** ```java public @Nullable String fieldName() throws TreeSitterLanguagePackRsException ``` **Example:** ```java var result = instance.fieldName(); ``` **Returns:** `@Nullable String` ###### close() [Section titled “close()”](#close-6) Releases the native handle backing this instance. Implements `AutoCloseable`; safe to call more than once. **Signature:** ```java public void close() throws TreeSitterLanguagePackRsException ``` **Example:** ```java instance.close(); ``` **Returns:** No return value. *** ### Enums [Section titled “Enums”](#enums) #### DataNodeKind [Section titled “DataNodeKind”](#datanodekind) The kind of a data node extracted from a data-format file. Classifies each node in the hierarchical `DataNode` tree returned when `data_extraction` is enabled on `ProcessConfig`. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract) Unit variants serialize as a bare string (`"KeyValue"`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | -------------------------------------------------------------------------------------------------------------------- | | `KEY_VALUE` | A key/value pair or mapping (json/toml/properties/yaml/hcl/cue/kdl pair, or a wrapper “object”/“mapping” container). | | `ELEMENT` | An XML element with a tag name in `key` and attributes in `attributes`. | | `SEQUENCE` | A positional sequence item (JSON array element, YAML block sequence item, CSV/PSV row or cell). | *** #### StructureKind [Section titled “StructureKind”](#structurekind) The kind of structural item found in source code. Categorizes top-level and nested declarations such as functions, classes, structs, enums, traits, and more. Use `Other` for language-specific constructs that do not fit a standard category. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-1) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | ---------------------------------------------------------------------------------------------- | | `FUNCTION` | A free-standing or associated function. | | `METHOD` | A method defined inside a class, struct, trait, or impl block. | | `CLASS` | A class definition. | | `STRUCT` | A struct definition. | | `INTERFACE` | An interface or protocol definition. | | `ENUM` | An enum definition. | | `MODULE` | A module or package declaration. | | `TRAIT` | A trait definition. | | `IMPL` | An impl block (Rust) or similar implementation block. | | `NAMESPACE` | A namespace declaration. | | `OTHER` | A language-specific construct that does not fit any standard category. — Fields: `0`: `String` | *** #### CommentKind [Section titled “CommentKind”](#commentkind) The kind of a comment found in source code. Distinguishes between single-line comments, block (multi-line) comments, and documentation comments. | Value | Description | | ------- | --------------------------------------------------------------------- | | `LINE` | A single-line comment (e.g., `// ...` or `# ...`). | | `BLOCK` | A block or multi-line comment using slash-star delimiters. | | `DOC` | A documentation comment such as `/// ...` or slash-double-star block. | *** #### DocstringFormat [Section titled “DocstringFormat”](#docstringformat) The format of a docstring extracted from source code. Identifies the docstring convention used, which varies by language (e.g., Python triple-quoted strings, JSDoc, Rustdoc `///` comments). ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-2) Unit variants serialize as a bare string (`"JSDoc"`); the `Other` variant serializes as a single-keyed object (`{"Other": "rst"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | --------------------- | -------------------------------------------------------------------------------------------------- | | `PYTHON_TRIPLE_QUOTE` | Python triple-quoted string docstring (`"""..."""`). | | `JS_DOC` | JavaScript/TypeScript JSDoc block comment (opens with two stars, closes with star-slash). | | `RUSTDOC` | Rust `///` or `//!` doc comment. | | `GO_DOC` | Go doc comment (a comment block immediately preceding a declaration). | | `JAVA_DOC` | Java Javadoc block comment (opens with two stars, closes with star-slash). | | `OTHER` | A language-specific docstring format not covered by the standard variants. — Fields: `0`: `String` | *** #### ExportKind [Section titled “ExportKind”](#exportkind) The kind of an export statement found in source code. Covers named exports, default exports, and re-exports from other modules. | Value | Description | | ----------- | -------------------------------------------------------------------- | | `NAMED` | A named export (e.g., `export { foo }`). | | `DEFAULT` | A default export (e.g., `export default foo`). | | `RE_EXPORT` | A re-export from another module (e.g., `export { foo } from 'bar'`). | *** #### SymbolKind [Section titled “SymbolKind”](#symbolkind) The kind of a symbol definition found in source code. Categorizes symbol definitions such as variables, constants, functions, classes, types, interfaces, enums, and modules. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-3) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | --------------------------------------------------------------------------- | | `VARIABLE` | A variable binding. | | `CONSTANT` | A constant (immutable binding). | | `FUNCTION` | A function definition. | | `CLASS` | A class definition. | | `TYPE` | A type alias or typedef. | | `INTERFACE` | An interface definition. | | `ENUM` | An enum definition. | | `MODULE` | A module declaration. | | `OTHER` | A symbol kind not covered by the standard variants. — Fields: `0`: `String` | *** #### DiagnosticSeverity [Section titled “DiagnosticSeverity”](#diagnosticseverity) Severity level of a diagnostic produced during parsing. Used to classify parse errors, warnings, and informational messages found in the syntax tree. | Value | Description | | --------- | --------------------------------------------------------------- | | `ERROR` | A parse error (e.g., an `ERROR` or `MISSING` node in the tree). | | `WARNING` | A warning-level diagnostic. | | `INFO` | An informational diagnostic. | *** ### Errors [Section titled “Errors”](#errors) #### Error [Section titled “Error”](#error) Errors that can occur when using the tree-sitter language pack. Covers language lookup failures, parse errors, query errors, and I/O issues. Feature-gated variants are included when `config`, `download`, or related features are enabled. ##### Matching on `Error` [Section titled “Matching on Error”](#matching-on-error) The set of variants is not stable: new failure modes are added in minor releases, and `Io`, `Json`, and `Toml` exist only under certain feature combinations, so the variant set a downstream crate sees depends on which features it enables. Downstream `match`es must therefore carry a `_` arm; `#[non_exhaustive]` makes the compiler enforce that instead of letting a feature change silently break a build. ##### C ABI error codes [Section titled “C ABI error codes”](#c-abi-error-codes) Each variant alef can see carries an explicit `alef(error_code = N)` allocation that becomes a member of the generated `AlefFfiErrorCode` C enum. These numbers are a public ABI contract: **an allocated number is never reused after its variant is removed**, and a variant’s number never changes, because C callers compare against the value, not the name. New variants take the next free number. 0-4 are reserved by alef, so allocation starts at 100. An unannotated variant is emitted as the unknown code rather than as itself, which silently flattens the taxonomy — annotate every new variant. | Variant | Description | | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `LanguageNotFoundException` | The requested language name (or alias) was not found in the registry. | | `DynamicLoadException` | A dynamic shared library could not be loaded at runtime. | | `NullLanguagePointerException` | The tree-sitter language function returned a null pointer for the given language name. | | `ParserSetupException` | The language could not be applied to the parser (e.g., ABI version mismatch). | | `LockPoisonedException` | An internal `RwLock` or `Mutex` was poisoned by a previous panic. | | `ConfigException` | A configuration file or value was invalid or could not be applied. | | `ParseFailedException` | The tree-sitter parser returned no tree for the given source input. | | `ParseTimeoutException` | The parse was cancelled because it exceeded its configured wall-clock budget. Raised only when a budget is configured — see `ProcessConfig.parse_timeout_ms`, which defaults to `null`. | | `QueryErrorException` | A tree-sitter query could not be compiled or executed. | | `InvalidRangeException` | A byte range was invalid (e.g., end before start, or out of bounds). | | `DownloadException` | A parser download from GitHub releases failed. | | `ChecksumMismatchException` | The downloaded file’s SHA-256 digest did not match the manifest’s expected value. | | `CacheLockException` | The cross-process download cache lock file could not be acquired or created. | *** # Kotlin (Android) API Reference ## Kotlin (Android) API Reference v1.16.1 [Section titled “Kotlin (Android) API Reference v1.16.1”](#kotlin-android-api-reference-v1161) ### Functions [Section titled “Functions”](#functions) #### detectLanguageFromExtension() [Section titled “detectLanguageFromExtension()”](#detectlanguagefromextension) Detect language name from a file extension (without leading dot). Returns `null` for unrecognized extensions. The match is case-insensitive. **Signature:** ```kotlin fun detectLanguageFromExtension(ext: String): String? ``` **Example:** ```kotlin val result = detectLanguageFromExtension("value") ``` **Parameters:** | Name | Type | Required | Description | | ----- | -------- | -------- | ----------- | | `ext` | `String` | Yes | The ext | **Returns:** `String?` *** #### detectLanguageFromPath() [Section titled “detectLanguageFromPath()”](#detectlanguagefrompath) Detect language name from a file path. Extracts the file extension and looks it up. Returns `null` if the path has no extension or the extension is not recognized. **Signature:** ```kotlin fun detectLanguageFromPath(path: String): String? ``` **Example:** ```kotlin val result = detectLanguageFromPath("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `path` | `String` | Yes | Path to the file | **Returns:** `String?` *** #### detectLanguageFromContent() [Section titled “detectLanguageFromContent()”](#detectlanguagefromcontent) Detect language name from file content using the shebang line (`#!`). Inspects only the first line of `content`. If it begins with `#!`, the interpreter name is extracted and mapped to a language name. Handles common patterns: * `#!/usr/bin/env python3` → `"python"` * `#!/bin/bash` → `"bash"` * `#!/usr/bin/env node` → `"javascript"` The `-S` flag accepted by some `env` implementations is skipped automatically. Version suffixes (e.g. `python3.11`, `ruby3.2`) are stripped before matching. A leading UTF-8 BOM (`U+FEFF`) is skipped before the `#!` check, so a BOM-prefixed script is still detected by its shebang. Returns `null` when content does not start with `#!` (after stripping a leading BOM), the shebang is malformed, or the interpreter is not recognised. **Signature:** ```kotlin fun detectLanguageFromContent(content: String): String? ``` **Example:** ```kotlin val result = detectLanguageFromContent("value") ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ---------------------- | | `content` | `String` | Yes | The content to process | **Returns:** `String?` *** #### getHighlightsQuery() [Section titled “getHighlightsQuery()”](#gethighlightsquery) Get the highlights query for a language, if bundled. Returns the contents of `highlights.scm` as a static string, or `null` if no highlights query is bundled for this language. **Signature:** ```kotlin fun getHighlightsQuery(language: String): String? ``` **Example:** ```kotlin val result = getHighlightsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getInjectionsQuery() [Section titled “getInjectionsQuery()”](#getinjectionsquery) Get the injections query for a language, if bundled. Returns the contents of `injections.scm` as a static string, or `null` if no injections query is bundled for this language. **Signature:** ```kotlin fun getInjectionsQuery(language: String): String? ``` **Example:** ```kotlin val result = getInjectionsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getLocalsQuery() [Section titled “getLocalsQuery()”](#getlocalsquery) Get the locals query for a language, if bundled. Returns the contents of `locals.scm` as a static string, or `null` if no locals query is bundled for this language. **Signature:** ```kotlin fun getLocalsQuery(language: String): String? ``` **Example:** ```kotlin val result = getLocalsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getTagsQuery() [Section titled “getTagsQuery()”](#gettagsquery) Get the tags query for a language, if bundled. Returns the contents of `tags.scm` as a static string, or `null` if no tags query is bundled for this language. **Signature:** ```kotlin fun getTagsQuery(language: String): String? ``` **Example:** ```kotlin val result = getTagsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getIndentsQuery() [Section titled “getIndentsQuery()”](#getindentsquery) Get the indents query for a language, if bundled. Returns the contents of `indents.scm` (used for auto-indentation) as a static string, or `null` if no indents query is bundled for this language. **Signature:** ```kotlin fun getIndentsQuery(language: String): String? ``` **Example:** ```kotlin val result = getIndentsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getFoldsQuery() [Section titled “getFoldsQuery()”](#getfoldsquery) Get the folds query for a language, if bundled. Returns the contents of `folds.scm` (used for code folding) as a static string, or `null` if no folds query is bundled for this language. **Signature:** ```kotlin fun getFoldsQuery(language: String): String? ``` **Example:** ```kotlin val result = getFoldsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getLanguage() [Section titled “getLanguage()”](#getlanguage) Get a tree-sitter `Language` by name using the global registry. Resolves language aliases (e.g., `"shell"` maps to `"bash"`). When the `download` feature is enabled (default), automatically downloads the parser from GitHub releases if not found locally. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.Download` if auto-download fails. **Signature:** ```kotlin @Throws(Error::class) fun getLanguage(name: String): Language ``` **Example:** ```kotlin val result = getLanguage("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Language` **Errors:** Throws `Error`. *** #### getParser() [Section titled “getParser()”](#getparser) Get a `Parser` pre-configured for the given language. This is a convenience function that calls `get_language` and configures a new parser in one step. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language cannot be applied to the parser. **Signature:** ```kotlin @Throws(Error::class) fun getParser(name: String): Parser ``` **Example:** ```kotlin val result = getParser("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Parser` **Errors:** Throws `Error`. *** #### detectLanguage() [Section titled “detectLanguage()”](#detectlanguage) Detect language name from a file path or extension. This compatibility alias matches the pre-Alef Python binding API. **Signature:** ```kotlin fun detectLanguage(path: String): String? ``` **Example:** ```kotlin val result = detectLanguage("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `path` | `String` | Yes | Path to the file | **Returns:** `String?` *** #### availableLanguages() [Section titled “availableLanguages()”](#availablelanguages) List all available language names (sorted, deduplicated, includes aliases). Returns names of both statically compiled and dynamically loadable languages, plus any configured aliases. **Signature:** ```kotlin fun availableLanguages(): List ``` **Example:** ```kotlin val result = availableLanguages() ``` **Returns:** `List` *** #### hasLanguage() [Section titled “hasLanguage()”](#haslanguage) Check if a language is available by name or alias. Returns `true` if the language can be loaded (statically compiled, dynamically available, or a known alias for one of these). **Signature:** ```kotlin fun hasLanguage(name: String): Boolean ``` **Example:** ```kotlin val result = hasLanguage("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Boolean` *** #### languageCount() [Section titled “languageCount()”](#languagecount) Return the number of available languages. Includes statically compiled languages, dynamically loadable languages, and aliases. **Signature:** ```kotlin fun languageCount(): Long ``` **Example:** ```kotlin val result = languageCount() ``` **Returns:** `Long` *** #### process() [Section titled “process()”](#process) Process source code and extract file intelligence using the global registry. Parses the source with tree-sitter and extracts metrics, structure, imports, exports, comments, docstrings, symbols, diagnostics, and/or chunks based on the flags set in `ProcessConfig`. **Errors:** Returns `Error.InvalidRange` if the config carries a zero-valued limit or the source exceeds `ProcessConfig.max_source_bytes`, `Error.ParseTimeout` if the parse exceeds `ProcessConfig.parse_timeout_ms`, `Error.LanguageNotFound` if the language is unknown, or `Error.ParseFailed` if parsing yields no tree. **Signature:** ```kotlin @Throws(Error::class) fun process(source: String, config: ProcessConfig): ProcessResult ``` **Example:** ```kotlin val result = process("value", ProcessConfig()) ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `String` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Throws `Error`. *** #### prefetch() [Section titled “prefetch()”](#prefetch) Prefetch grammars by loading each into the registry. Without the `download` feature there is no network step — every requested language must already be statically compiled or present on disk. **Errors:** Returns `Error.LanguageNotFound` if a requested language is not available. **Signature:** ```kotlin @Throws(Error::class) fun prefetch(languages: List) ``` **Example:** ```kotlin prefetch([]) ``` **Parameters:** | Name | Type | Required | Description | | ----------- | -------------- | -------- | ------------- | | `languages` | `List` | Yes | The languages | **Returns:** No return value. **Errors:** Throws `Error`. *** ### Types [Section titled “Types”](#types) #### ByteRange [Section titled “ByteRange”](#byterange) A byte range — start (inclusive) to end (exclusive). | Field | Type | Default | Description | | ------- | ------ | ------- | ---------------------------- | | `start` | `Long` | — | Inclusive start byte offset. | | `end` | `Long` | — | Exclusive end byte offset. | *** #### ChunkContext [Section titled “ChunkContext”](#chunkcontext) Metadata for a single chunk of source code. | Field | Type | Default | Description | | ---------------- | --------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String` | — | Language name used to parse this chunk. | | `chunkIndex` | `Long` | — | Zero-indexed position of this chunk within the file’s chunk list. | | `totalChunks` | `Long` | — | Total number of chunks the file was split into. | | `nodeTypes` | `List` | `[]` | Tree-sitter node kinds that appear at the top level of this chunk. | | `contextPath` | `List` | `[]` | Hierarchical path of enclosing structural items (e.g., `["MyClass", "my_method"]`). | | `symbolsDefined` | `List` | `[]` | Names of symbols defined within this chunk. | | `comments` | `List` | `[]` | Comments contained within this chunk. | | `docstrings` | `List` | `[]` | Docstrings contained within this chunk. Populated only for Python — the same language for which `ProcessResult.docstrings` is populated, and by the same classifier. Always empty for every other language. | | `hasErrorNodes` | `Boolean` | — | Whether this chunk contains any tree-sitter error nodes. | *** #### CodeChunk [Section titled “CodeChunk”](#codechunk) A chunk of source code with rich metadata. | Field | Type | Default | Description | | ----------- | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `content` | `String` | — | The raw source text of this chunk. | | `startByte` | `Long` | — | Inclusive start byte offset of this chunk in the original source. | | `endByte` | `Long` | — | Exclusive end byte offset of this chunk in the original source. | | `startLine` | `Long` | — | Zero-indexed start line of this chunk. | | `endLine` | `Long` | — | Zero-indexed row of the last byte actually included in this chunk (inclusive — the same row a `Span.end_line` would report for a node ending on that byte). Computed the same way regardless of whether the source has a trailing newline: it is always the row of `end_byte - 1`, never a phantom row past the file’s real content. | | `metadata` | `ChunkContext` | — | Contextual metadata about this chunk. | *** #### CommentInfo [Section titled “CommentInfo”](#commentinfo) A comment extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------- | ------------------ | ----------------------------------------------------------------- | | `text` | `String` | — | The raw text content of the comment. | | `kind` | `CommentKind` | `CommentKind.Line` | The kind of comment (line, block, or doc). | | `span` | `Span` | — | Source span covering the comment. | | `associatedNode` | `String?` | `null` | Name of the syntax node this comment is directly associated with. | *** #### DataAttribute [Section titled “DataAttribute”](#dataattribute) An XML-style attribute attached to an `Element` node. Populated only for `DataNodeKind.Element`; always empty for `KeyValue` and `Sequence` nodes. | Field | Type | Default | Description | | ------- | -------- | ------- | --------------------------------------------------------------- | | `name` | `String` | — | Attribute name (e.g. `"class"`, `"href"`). | | `value` | `String` | — | Attribute value as a raw string (quotes stripped). | | `span` | `Span` | — | Source span covering the entire `name="value"` attribute token. | *** #### DataNode [Section titled “DataNode”](#datanode) A node in the hierarchical data tree produced by data-format extraction. When `ProcessConfig.data_extraction` is `true`, `ProcessResult.data` is populated with a root `DataNode` whose `children` mirror the structure of the parsed file. The `kind` field determines which other fields are meaningful: | `kind` | `key` | `value` | `attributes` | `children` | | ---------- | ------------------------- | ------------ | ------------ | -------------- | | `KeyValue` | key / mapping key / index | leaf value | empty | nested map | | `Element` | XML tag name | text content | XML attrs | child elements | | `Sequence` | positional index (`"0"`) | leaf value | empty | sub-items | | Field | Type | Default | Description | | ------------ | --------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------- | | `kind` | `DataNodeKind` | `DataNodeKind.KeyValue` | Whether this node is a key/value pair, XML element, or sequence item. | | `key` | `String?` | `null` | Key, attribute name, tag name, or positional index (`"0"`, `"1"`, …). `null` at the document root. | | `value` | `String?` | `null` | Leaf scalar value, if any. `null` for containers (objects, arrays, XML elements with child elements). | | `attributes` | `List` | `[]` | Attributes on element-shape nodes (XML `STag` attributes). Empty for all other kinds. | | `children` | `List` | `[]` | Children for nested containers and XML element bodies. | | `span` | `Span` | — | Source span covering this node in the original source file. | *** #### Diagnostic [Section titled “Diagnostic”](#diagnostic) A diagnostic (syntax error, missing node, etc.) from parsing. | Field | Type | Default | Description | | ---------- | -------------------- | -------------------------- | ---------------------------------------------- | | `message` | `String` | — | Human-readable description of the diagnostic. | | `severity` | `DiagnosticSeverity` | `DiagnosticSeverity.Error` | Severity of the diagnostic. | | `span` | `Span` | — | Source span where the diagnostic was detected. | *** #### DocSection [Section titled “DocSection”](#docsection) A section within a docstring (e.g., Args, Returns, Raises). | Field | Type | Default | Description | | ------------- | --------- | ------- | ------------------------------------------------------- | | `kind` | `String` | — | Section kind (e.g., `"args"`, `"returns"`, `"raises"`). | | `name` | `String?` | `null` | Parameter or return value name, if applicable. | | `description` | `String` | — | Description text for this section. | *** #### DocstringInfo [Section titled “DocstringInfo”](#docstringinfo) A docstring extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------------ | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | `String` | — | The raw text of the docstring. | | `format` | `DocstringFormat` | `DocstringFormat.PythonTripleQuote` | The docstring format (Python, JSDoc, Rustdoc, etc.). | | `span` | `Span` | — | Source span covering the docstring. | | `associatedItem` | `String?` | `null` | Name of the item this docstring documents. | | `parsedSections` | `List` | `[]` | Parsed sections of the docstring (Args, Returns, Raises, etc.). **Reserved: not yet populated.** Always empty, for every `DocstringFormat`. Parsing a docstring body into sections requires implementing each convention’s own layout (Google/NumPy/reST style for Python, `@param`/`@returns` for JSDoc/Javadoc, and so on), which no extractor here does yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | *** #### ExportInfo [Section titled “ExportInfo”](#exportinfo) An export statement extracted from source code. | Field | Type | Default | Description | | ------ | ------------ | ------------------ | -------------------------------------------------- | | `name` | `String` | — | The exported name. | | `kind` | `ExportKind` | `ExportKind.Named` | The kind of export (named, default, or re-export). | | `span` | `Span` | — | Source span covering the export statement. | *** #### FileMetrics [Section titled “FileMetrics”](#filemetrics) Aggregate metrics for a source file. | Field | Type | Default | Description | | -------------- | ------ | ------- | -------------------------------------------------------------- | | `totalLines` | `Long` | — | Total number of lines (including blank and comment lines). | | `codeLines` | `Long` | — | Number of lines containing non-blank, non-comment source code. | | `commentLines` | `Long` | — | Number of lines that are entirely comments. | | `blankLines` | `Long` | — | Number of blank (whitespace-only) lines. | | `totalBytes` | `Long` | — | Total byte length of the source file. | | `nodeCount` | `Long` | — | Total number of nodes in the syntax tree. | | `errorCount` | `Long` | — | Number of error nodes in the syntax tree (parse errors). | | `maxDepth` | `Long` | — | Maximum nesting depth reached in the syntax tree. | *** #### ImportInfo [Section titled “ImportInfo”](#importinfo) An import statement extracted from source code. | Field | Type | Default | Description | | ------------ | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `source` | `String` | — | The module or path being imported from. | | `items` | `List` | `[]` | Specific names imported from the source module. For `import a, b` / `from m import a, b`, every entry’s base name (never the alias). For a JavaScript/TypeScript named-imports clause (`import { a, b as c } from 'm'`), every specifier’s original name. Populated for Python and JavaScript/TypeScript only. Always empty for every other language this library recognises import statements for — Rust, Go, Java, Kotlin, and Elixir (`import`/`alias`/`require`/`use`) — and for a JS/TS namespace import (`import * as ns`) or default import (`import x from 'm'`), neither of which names individual items. | | `alias` | `String?` | `null` | Alias assigned to the import (e.g., `import numpy as np`). Populated for Python’s single-name form (`import numpy as np`, `from m import a as b`) and JavaScript/TypeScript’s namespace form (`import * as ns from 'm'`) or a named-imports clause naming exactly one specifier (`import { a as b } from 'm'`). `null` for Rust, Go, Java, Kotlin, and Elixir (which has its own `as:` alias option on `alias` directives, not yet extracted here) — and for a Python statement that aliases several names at once (`import os, sys as s`), where there is no single alias to report for the statement as a whole, so only `items` is populated for it. | | `isWildcard` | `Boolean` | — | Whether this is a wildcard import (e.g., `import *` or `use foo.*`). Detected from the syntax tree — a dedicated wildcard node (`wildcard_import` in Python, `use_wildcard` in Rust) or a bare `*` token outside of string-literal content — not by searching the import’s source text for a `*` character, so a glob in an import path string (`import a from './glob*.js'`) is not mistaken for one. | | `span` | `Span` | — | Source span covering the import statement. | *** #### Language [Section titled “Language”](#language) *** #### LanguageRegistry [Section titled “LanguageRegistry”](#languageregistry) Thread-safe registry of tree-sitter language parsers. Manages both statically compiled and dynamically loaded language grammars. Use `LanguageRegistry.new()` for the default registry, or access the global instance via the module-level convenience functions (`get_language`, `available_languages`, etc.). ##### Methods [Section titled “Methods”](#methods) ###### new() [Section titled “new()”](#new) Create a new registry populated with all statically compiled languages. When the `dynamic-loading` feature is enabled, the registry also knows about dynamically loadable grammars and will load them on demand. **Signature:** ```kotlin @JvmStatic fun new(): LanguageRegistry ``` **Example:** ```kotlin val result = LanguageRegistry.new() ``` **Returns:** `LanguageRegistry` ###### getLanguage() [Section titled “getLanguage()”](#getlanguage-1) Get a tree-sitter `Language` by name. Resolves aliases (e.g., `"shell"` -> `"bash"`, `"makefile"` -> `"make"`), then looks up the language in the static table. When the `dynamic-loading` feature is enabled, falls back to loading a shared library on demand. **Errors:** Returns `Error.LanguageNotFound` if the name (after alias resolution) does not match any known grammar. **Signature:** ```kotlin @Throws(Error::class) fun getLanguage(name: String): Language ``` **Example:** ```kotlin val result = instance.getLanguage("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Language` **Errors:** Throws `Error`. ###### availableLanguages() [Section titled “availableLanguages()”](#availablelanguages-1) List all available language names, sorted and deduplicated. Includes statically compiled languages, dynamically loadable languages (if the `dynamic-loading` feature is enabled), and all configured aliases. **Signature:** ```kotlin fun availableLanguages(): List ``` **Example:** ```kotlin val result = instance.availableLanguages() ``` **Returns:** `List` ###### hasParser() [Section titled “hasParser()”](#hasparser) Check whether this language can be parsed right now, without downloading. Resolves aliases, then answers from exactly the lookup `get_language` performs: the statically compiled table, the already-loaded dynamic grammars, and the parser shared libraries present in the primary and extra (download-cache) library directories. It never performs network I/O. A previous implementation consulted only the statically compiled table. That table is empty in every build that does not set `TSLP_LANGUAGES`, so the function answered `false` for languages this registry parses perfectly well. Contrast `has_language`, which is also `true` for a grammar that is merely *known to the manifest* and would have to be downloaded first. The pair distinguishes “we can parse it offline, now” from “we recognise the name”. The first `true` answer for a dynamic grammar loads its shared library: loading is the only way to know the grammar is usable, since a truncated or wrong-architecture library exists on disk but cannot parse. Loads are cached process-wide, so repeat calls are cheap. **Signature:** ```kotlin fun hasParser(name: String): Boolean ``` **Example:** ```kotlin val result = instance.hasParser("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Boolean` ###### hasLanguage() [Section titled “hasLanguage()”](#haslanguage-1) Check whether a language is available by name or alias. Returns `true` if the language can be loaded, either from the static table or from a dynamic library on disk. Every branch is one more way to answer `true`, so they are ordered cheapest-first and the filesystem is only consulted once every in-memory source has said no. Probing the loaded-grammar map and the manifest ahead of the `stat` calls is what keeps this off the syscall path for the languages a process actually uses. **Signature:** ```kotlin fun hasLanguage(name: String): Boolean ``` **Example:** ```kotlin val result = instance.hasLanguage("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Boolean` ###### languageCount() [Section titled “languageCount()”](#languagecount-1) Return the total number of available languages (including aliases). Counts the same set `available_languages` lists, without materialising or sorting it. **Signature:** ```kotlin fun languageCount(): Long ``` **Example:** ```kotlin val result = instance.languageCount() ``` **Returns:** `Long` ###### process() [Section titled “process()”](#process-1) Parse source code and extract file intelligence based on config in a single pass. **Errors:** Returns `Error.InvalidRange` if the config is invalid (see `ProcessConfig.validate`) or if the source exceeds the configured `max_source_bytes`; `Error.LanguageNotFound` if the language is unknown; or `Error.ParseFailed` if parsing produces no tree. **Signature:** ```kotlin @Throws(Error::class) fun process(source: String, config: ProcessConfig): ProcessResult ``` **Example:** ```kotlin val result = instance.process("value", ProcessConfig()) ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `String` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Throws `Error`. *** #### Node [Section titled “Node”](#node) A single syntax node within a `Tree`. Nodes hold a strong reference to their parent tree so they remain valid regardless of how the tree is moved or stored at the FFI boundary. ##### Methods [Section titled “Methods”](#methods-1) ###### kind() [Section titled “kind()”](#kind) Return the node’s kind name (e.g. `"function_definition"`). **Signature:** ```kotlin fun kind(): String ``` **Example:** ```kotlin val result = instance.kind() ``` **Returns:** `String` ###### kindId() [Section titled “kindId()”](#kindid) Return the node’s numeric kind ID. Tree-sitter assigns a stable `u16` ID to every node kind in a grammar (e.g. `"function_definition" → 42`). Comparing `kind_id()` is cheaper than comparing the string `kind()` in tight AST loops. **Signature:** ```kotlin fun kindId(): Short ``` **Example:** ```kotlin val result = instance.kindId() ``` **Returns:** `Short` ###### startByte() [Section titled “startByte()”](#startbyte) Return the inclusive start byte offset of this node. **Signature:** ```kotlin fun startByte(): Long ``` **Example:** ```kotlin val result = instance.startByte() ``` **Returns:** `Long` ###### endByte() [Section titled “endByte()”](#endbyte) Return the exclusive end byte offset of this node. **Signature:** ```kotlin fun endByte(): Long ``` **Example:** ```kotlin val result = instance.endByte() ``` **Returns:** `Long` ###### byteRange() [Section titled “byteRange()”](#byterange-1) Return the node’s byte range as a `ByteRange`. Callers should slice their own source bytes — this is a zero-copy text accessor. **Signature:** ```kotlin fun byteRange(): ByteRange ``` **Example:** ```kotlin val result = instance.byteRange() ``` **Returns:** `ByteRange` ###### startPosition() [Section titled “startPosition()”](#startposition) Return the start `Point` (row, column). **Signature:** ```kotlin fun startPosition(): Point ``` **Example:** ```kotlin val result = instance.startPosition() ``` **Returns:** `Point` ###### endPosition() [Section titled “endPosition()”](#endposition) Return the end `Point` (row, column). **Signature:** ```kotlin fun endPosition(): Point ``` **Example:** ```kotlin val result = instance.endPosition() ``` **Returns:** `Point` ###### isNamed() [Section titled “isNamed()”](#isnamed) True when this node is named (not punctuation/whitespace). **Signature:** ```kotlin fun isNamed(): Boolean ``` **Example:** ```kotlin val result = instance.isNamed() ``` **Returns:** `Boolean` ###### isError() [Section titled “isError()”](#iserror) True when this is an error node. **Signature:** ```kotlin fun isError(): Boolean ``` **Example:** ```kotlin val result = instance.isError() ``` **Returns:** `Boolean` ###### isMissing() [Section titled “isMissing()”](#ismissing) True when this is a missing-token node. **Signature:** ```kotlin fun isMissing(): Boolean ``` **Example:** ```kotlin val result = instance.isMissing() ``` **Returns:** `Boolean` ###### isExtra() [Section titled “isExtra()”](#isextra) True when this is an “extra” node (e.g. a comment). **Signature:** ```kotlin fun isExtra(): Boolean ``` **Example:** ```kotlin val result = instance.isExtra() ``` **Returns:** `Boolean` ###### hasError() [Section titled “hasError()”](#haserror) True when this node or any descendant is an error. **Signature:** ```kotlin fun hasError(): Boolean ``` **Example:** ```kotlin val result = instance.hasError() ``` **Returns:** `Boolean` ###### parent() [Section titled “parent()”](#parent) Return this node’s parent, if any. **Signature:** ```kotlin fun parent(): Node? ``` **Example:** ```kotlin val result = instance.parent() ``` **Returns:** `Node?` ###### child() [Section titled “child()”](#child) Return the i-th child of this node, if any. **Signature:** ```kotlin fun child(index: Int): Node? ``` **Example:** ```kotlin val result = instance.child(42) ``` **Parameters:** | Name | Type | Required | Description | | ------- | ----- | -------- | ----------- | | `index` | `Int` | Yes | The index | **Returns:** `Node?` ###### childCount() [Section titled “childCount()”](#childcount) Total number of children (including unnamed). **Signature:** ```kotlin fun childCount(): Long ``` **Example:** ```kotlin val result = instance.childCount() ``` **Returns:** `Long` ###### namedChild() [Section titled “namedChild()”](#namedchild) Return the i-th named child of this node, if any. **Signature:** ```kotlin fun namedChild(index: Int): Node? ``` **Example:** ```kotlin val result = instance.namedChild(42) ``` **Parameters:** | Name | Type | Required | Description | | ------- | ----- | -------- | ----------- | | `index` | `Int` | Yes | The index | **Returns:** `Node?` ###### namedChildCount() [Section titled “namedChildCount()”](#namedchildcount) Number of named children of this node. **Signature:** ```kotlin fun namedChildCount(): Long ``` **Example:** ```kotlin val result = instance.namedChildCount() ``` **Returns:** `Long` ###### childByFieldName() [Section titled “childByFieldName()”](#childbyfieldname) Look up a child by its grammar-defined field name. **Signature:** ```kotlin fun childByFieldName(name: String): Node? ``` **Example:** ```kotlin val result = instance.childByFieldName("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Node?` ###### toSexp() [Section titled “toSexp()”](#tosexp) Return the S-expression form of this node’s subtree. **Signature:** ```kotlin fun toSexp(): String ``` **Example:** ```kotlin val result = instance.toSexp() ``` **Returns:** `String` ###### walk() [Section titled “walk()”](#walk) Return a `TreeCursor` positioned at this node. **Signature:** ```kotlin fun walk(): TreeCursor ``` **Example:** ```kotlin val result = instance.walk() ``` **Returns:** `TreeCursor` *** #### PackConfig [Section titled “PackConfig”](#packconfig) Configuration for the tree-sitter language pack. Controls cache directory and which languages to pre-download. Can be loaded from a TOML file, constructed programmatically, or passed as a dict/object from language bindings. | Field | Type | Default | Description | | ----------- | --------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cacheDir` | `Path?` | `null` | Override the BASE directory the parser cache lives under. This is a base, not the final library path: the crate appends `tree-sitter-language-pack/v{version}/libs` to it, exactly as it does to the platform default. So `cache_dir = "/tmp/my-parsers"` resolves to `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`. The suffix is not cosmetic. It keeps the whole cache tree — manifest, bundles and lock file included — inside a directory this library owns and versions. Earlier releases used this path verbatim, which put those files in the configured directory’s PARENT and let a cache built by one crate version be reused by another. Default base: the platform cache dir, e.g. `~/.cache` on Linux. | | `languages` | `List?` | `[]` | Languages to pre-download on init. Each entry is a language name (e.g. `"python"`, `"rust"`). | | `groups` | `List?` | `[]` | Language groups to pre-download. Group names come from the remote manifest, so the valid set is not fixed by this library; the published manifest currently defines only `"all"`. Call `manifest_groups` to enumerate them. An unknown name makes `init` fail. | *** #### Parser [Section titled “Parser”](#parser) A tree-sitter parser configured for one language at a time. ##### Methods [Section titled “Methods”](#methods-2) ###### new() [Section titled “new()”](#new-1) Construct a new parser with no language set and no parse limits. Call `Parser.set_language` before parsing. Limits are opt-in via `set_max_source_bytes` and `set_parse_timeout_ms`; both default to unbounded so that existing callers are unaffected. **Signature:** ```kotlin @JvmStatic fun new(): Parser ``` **Example:** ```kotlin val result = Parser.new() ``` **Returns:** `Parser` ###### setMaxSourceBytes() [Section titled “setMaxSourceBytes()”](#setmaxsourcebytes) Refuse to parse sources longer than `max_bytes`. `null` (the default) means no limit. Over-limit input makes `parse` and `parse_bytes` return `null` after emitting a `WARN`; input is never silently truncated. See `RECOMMENDED_MAX_SOURCE_BYTES`. **Signature:** ```kotlin fun setMaxSourceBytes(maxBytes: Long? = null) ``` **Example:** ```kotlin instance.setMaxSourceBytes(42) ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------- | -------- | ------------- | | `maxBytes` | `Long?` | No | The max bytes | **Returns:** No return value. ###### setParseTimeoutMs() [Section titled “setParseTimeoutMs()”](#setparsetimeoutms) Cancel a parse that exceeds `timeout_ms` milliseconds of wall clock. `null` (the default) means no budget. Cancellation runs through tree-sitter’s parse progress callback, so it is granular to that callback’s interval rather than exact. See `RECOMMENDED_PARSE_TIMEOUT_MS`. **Signature:** ```kotlin fun setParseTimeoutMs(timeoutMs: Long? = null) ``` **Example:** ```kotlin instance.setParseTimeoutMs(42) ``` **Parameters:** | Name | Type | Required | Description | | ----------- | ------- | -------- | -------------- | | `timeoutMs` | `Long?` | No | The timeout ms | **Returns:** No return value. ###### setLanguage() [Section titled “setLanguage()”](#setlanguage) Configure the parser to use the language identified by name (e.g. `"python"`). Resolves the language through the global registry — auto-downloading if necessary, when the `download` feature is enabled. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language ABI is incompatible. **Signature:** ```kotlin @Throws(Error::class) fun setLanguage(name: String) ``` **Example:** ```kotlin instance.setLanguage("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** No return value. **Errors:** Throws `Error`. ###### parse() [Section titled “parse()”](#parse) Parse a UTF-8 source string. Returns `null` if no language is set, if the parse was cancelled by the configured timeout, or if the source exceeds the configured size limit. Each non-parse outcome is logged, so an empty result is never silent. ###### Concurrency [Section titled “Concurrency”](#concurrency) Parsing runs fully in parallel across threads for almost every language — no lock is taken. The exception is the small set of grammars whose external scanner keeps mutable process-global state (currently just `properties`): parses of that language are serialized against each other through an internal per-language lock, so that concurrent threads can’t corrupt shared scanner state. Every other language is unaffected by that lock and never waits on it. **Signature:** ```kotlin fun parse(source: String): Tree? ``` **Example:** ```kotlin val result = instance.parse("value") ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------- | -------- | ----------- | | `source` | `String` | Yes | The source | **Returns:** `Tree?` ###### parseBytes() [Section titled “parseBytes()”](#parsebytes) Parse a raw byte slice. Same outcomes as `parse`, including the concurrency behaviour documented there. **Signature:** ```kotlin fun parseBytes(source: ByteArray): Tree? ``` **Example:** ```kotlin val result = instance.parseBytes("data".toByteArray()) ``` **Parameters:** | Name | Type | Required | Description | | -------- | ----------- | -------- | ----------- | | `source` | `ByteArray` | Yes | The source | **Returns:** `Tree?` ###### reset() [Section titled “reset()”](#reset) Reset internal state. The next call to `parse` will not be incremental. **Signature:** ```kotlin fun reset() ``` **Example:** ```kotlin instance.reset() ``` **Returns:** No return value. *** #### Point [Section titled “Point”](#point) A source position — row + column, zero-indexed. | Field | Type | Default | Description | | -------- | ------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `row` | `Long` | — | Zero-indexed row number. | | `column` | `Long` | — | Zero-indexed column, counted in **bytes** from the start of the row. This is `tree_sitter.Point.column` verbatim, and tree-sitter defines it as a byte offset — not characters, and not UTF-16 code units. Measured on a row of the form `x = ''` where `` is a single 4-byte character (an emoji), the string node reports columns `4..10`, identical to its byte range; the character columns would be `4..7` and the UTF-16 columns `4..8`. Anything that builds LSP positions (UTF-16) or editor caret columns (characters) from this field is silently wrong on every row containing a non-ASCII byte, and must re-measure the row against the source text instead. Earlier releases documented this field as UTF-16 code units; that was never what the value contained. | *** #### ProcessConfig [Section titled “ProcessConfig”](#processconfig) Configuration for the `process()` function. Controls which analysis features are enabled and whether chunking is performed. | Field | Type | Default | Description | | ---------------- | --------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String` | `""` | Language name (required). | | `structure` | `Boolean` | `true` | Extract structural items (functions, classes, etc.). Default: true. | | `imports` | `Boolean` | `true` | Extract import statements. Default: true. | | `exports` | `Boolean` | `true` | Extract export statements. Default: true. | | `comments` | `Boolean` | `false` | Extract comments. Default: false. | | `docstrings` | `Boolean` | `false` | Extract docstrings. Default: false. | | `symbols` | `Boolean` | `false` | Extract symbol definitions. Default: false. | | `diagnostics` | `Boolean` | `false` | Include parse diagnostics. Default: false. | | `chunkMaxSize` | `Long?` | `null` | Maximum chunk size in bytes. `null` disables chunking. `Some(0)` is rejected by `ProcessConfig.validate` with `Error.InvalidRange`. A zero-sized chunk limit previously produced an empty chunk list and silently discarded the whole source; use `null` to mean “do not chunk”. | | `dataExtraction` | `Boolean` | `false` | Extract hierarchical key/value data tree from data-format files. Default: false. When `true`, `ProcessResult.data` is populated with a `DataNode` tree for supported languages: JSON, YAML, TOML, `.properties`, HCL/HOCON, INI, editorconfig, KDL, CUE, CSV, PSV, PO, nginx config, Caddy config, XML, and DTD. For languages outside this set the field is left as `null`. | | `maxSourceBytes` | `Long?` | `null` | Reject source longer than this many bytes instead of parsing it. Default: `null` (unbounded). Tree-sitter allocates and walks proportionally to input size, so an unbounded parse of attacker-supplied input is a denial-of-service vector. The default stays unbounded for backward compatibility; services handling untrusted input should opt in, e.g. with `RECOMMENDED_MAX_SOURCE_BYTES`. Exceeding the limit fails the call with `Error.InvalidRange` — the source is never silently truncated. | | `parseTimeoutMs` | `Long?` | `null` | Wall-clock budget for the parse step, in milliseconds. Default: `null` (no timeout). Enforced through tree-sitter’s parse progress callback, which the parser invokes periodically; cancellation is therefore granular to that callback interval rather than exact. A parse that exceeds the budget fails with `Error.ParseTimeout`. | *** #### ProcessResult [Section titled “ProcessResult”](#processresult) Complete analysis result from processing a source file. Contains metrics, structural analysis, imports/exports, comments, docstrings, symbols, diagnostics, and optionally chunked code segments. Fields are populated based on the `ProcessConfig` flags. | Field | Type | Default | Description | | ------------- | --------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String` | — | The language name used to parse the source file. | | `metrics` | `FileMetrics` | — | File-level metrics (line counts, byte size, error count). | | `structure` | `List` | `[]` | Top-level structural items (functions, classes, etc.). | | `imports` | `List` | `[]` | Import statements extracted from the source. | | `exports` | `List` | `[]` | Export statements extracted from the source. | | `comments` | `List` | `[]` | Comments extracted from the source. | | `docstrings` | `List` | `[]` | Docstrings extracted from the source. | | `symbols` | `List` | `[]` | Symbol definitions (variables, types, functions) extracted from the source. | | `diagnostics` | `List` | `[]` | Parse diagnostics (syntax errors, missing nodes) from tree-sitter. | | `chunks` | `List` | `[]` | Syntax-aware code chunks produced when chunking is enabled. | | `data` | `DataNode?` | `null` | Hierarchical data tree extracted when `config.data_extraction` is `true`. Populated for supported data-format languages (JSON, YAML, TOML, properties, HCL, INI, XML, CSV, and more). `null` when `data_extraction` is `false` (the default) or when the language is not a recognised data format. See `DataNode` for the shape of the returned tree. | *** #### Span [Section titled “Span”](#span) Byte and line/column range in source code. Represents both byte offsets (for slicing) and human-readable line/column positions (for display and diagnostics). | Field | Type | Default | Description | | ------------- | ------ | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `startByte` | `Long` | — | Inclusive start byte offset in the source. | | `endByte` | `Long` | — | Exclusive end byte offset in the source. | | `startLine` | `Long` | — | Zero-indexed line number of the span’s start. | | `startColumn` | `Long` | — | Zero-indexed column of the span’s start, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | | `endLine` | `Long` | — | Zero-indexed line number of the span’s end. | | `endColumn` | `Long` | — | Zero-indexed column of the span’s end, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | *** #### StructureItem [Section titled “StructureItem”](#structureitem) A structural item (function, class, struct, etc.) in source code. | Field | Type | Default | Description | | ------------ | --------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `kind` | `StructureKind` | `StructureKind.Function` | The kind of structural item. | | `name` | `String?` | `null` | The declared name of the item, if present. | | `visibility` | `String?` | `null` | Visibility modifier (e.g., `"pub"`, `"public"`, `"private"`). | | `span` | `Span` | — | Source span covering the entire item declaration. | | `children` | `List` | `[]` | Nested structural items (e.g., methods within a class). | | `decorators` | `List` | `[]` | Decorator or attribute names applied to the item. **Reserved: not yet populated.** Always empty, for every language. Recognising a decorator requires per-language grammar knowledge (a Python `decorated_definition` wrapper, Java/C# annotations, Rust attributes each have a different shape), which no extractor here implements yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | | `docComment` | `String?` | `null` | Documentation comment attached to the item, if any. The text of the comment (or run of comments) immediately preceding the item, with no blank line in between, when that comment is classified as a doc comment. Multiple adjacent single-line doc comments (Rust `///`) are joined with `\n` in source order. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`). `null` for every other language, and for a preceding comment that is not in doc-comment form (a plain `#` comment in Python, Ruby, or Elixir) — Python’s docstring convention is captured separately, as `DocstringInfo`, not through this field. | | `signature` | `String?` | `null` | Full signature text of the item (e.g., function parameters and return type). The item’s own source text from its start up to the start of its body (see `StructureItem.body_span`), trimmed of trailing whitespace — for example `fn add(a: i32, b: i32) -> i32` for a Rust function whose body is `{ a + b }`. `null` only when that text is empty, which does not happen for any item `StructureKind` currently reports. Populated for every language and kind this library extracts structure for, since it is derived from `body_span`’s boundary rather than per-language syntax. | | `bodySpan` | `Span?` | `null` | Source span covering only the body of the item, if distinct from the declaration. | *** #### SymbolInfo [Section titled “SymbolInfo”](#symbolinfo) A symbol (variable, function, type, etc.) extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------ | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `String` | — | The name of the symbol. | | `kind` | `SymbolKind` | `SymbolKind.Variable` | The kind of symbol (variable, function, class, etc.). | | `span` | `Span` | — | Source span covering the symbol definition. | | `typeAnnotation` | `String?` | `null` | Explicit type annotation, if present in the source. | | `doc` | `String?` | `null` | Documentation comment immediately preceding this symbol, resolved by the same walk `StructureItem.doc_comment` uses (see `doc_comment_at`) — never hard-coded `null`. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`) — the languages whose comment classification recognizes a doc-kind comment. `null` for every other language (e.g. Python, Go, Ruby, which have no doc-kind comment classification), and also `null` when a symbol in a supported language simply has no doc comment immediately above it. | *** #### Tree [Section titled “Tree”](#tree) A parsed syntax tree. Cheap to clone (refcount bump). ##### Methods [Section titled “Methods”](#methods-3) ###### rootNode() [Section titled “rootNode()”](#rootnode) Return the root `Node` of this tree. **Signature:** ```kotlin fun rootNode(): Node ``` **Example:** ```kotlin val result = instance.rootNode() ``` **Returns:** `Node` ###### walk() [Section titled “walk()”](#walk-1) Return a `TreeCursor` positioned at the root. **Signature:** ```kotlin fun walk(): TreeCursor ``` **Example:** ```kotlin val result = instance.walk() ``` **Returns:** `TreeCursor` *** #### TreeCursor [Section titled “TreeCursor”](#treecursor) A cursor for traversing a `Tree`. ##### Methods [Section titled “Methods”](#methods-4) ###### node() [Section titled “node()”](#node-1) Return the `Node` at the cursor’s current position. **Signature:** ```kotlin fun node(): Node ``` **Example:** ```kotlin val result = instance.node() ``` **Returns:** `Node` ###### gotoFirstChild() [Section titled “gotoFirstChild()”](#gotofirstchild) Move the cursor to the first child of the current node. Returns `true` if a child existed. **Signature:** ```kotlin fun gotoFirstChild(): Boolean ``` **Example:** ```kotlin val result = instance.gotoFirstChild() ``` **Returns:** `Boolean` ###### gotoParent() [Section titled “gotoParent()”](#gotoparent) Move the cursor to the parent of the current node. Returns `true` if a parent existed. **Signature:** ```kotlin fun gotoParent(): Boolean ``` **Example:** ```kotlin val result = instance.gotoParent() ``` **Returns:** `Boolean` ###### gotoNextSibling() [Section titled “gotoNextSibling()”](#gotonextsibling) Move the cursor to the next sibling of the current node. Returns `true` if a sibling existed. **Signature:** ```kotlin fun gotoNextSibling(): Boolean ``` **Example:** ```kotlin val result = instance.gotoNextSibling() ``` **Returns:** `Boolean` ###### fieldName() [Section titled “fieldName()”](#fieldname) Return the field name for the current node, if any. **Signature:** ```kotlin fun fieldName(): String? ``` **Example:** ```kotlin val result = instance.fieldName() ``` **Returns:** `String?` *** ### Enums [Section titled “Enums”](#enums) #### DataNodeKind [Section titled “DataNodeKind”](#datanodekind) The kind of a data node extracted from a data-format file. Classifies each node in the hierarchical `DataNode` tree returned when `data_extraction` is enabled on `ProcessConfig`. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract) Unit variants serialize as a bare string (`"KeyValue"`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ---------- | -------------------------------------------------------------------------------------------------------------------- | | `KeyValue` | A key/value pair or mapping (json/toml/properties/yaml/hcl/cue/kdl pair, or a wrapper “object”/“mapping” container). | | `Element` | An XML element with a tag name in `key` and attributes in `attributes`. | | `Sequence` | A positional sequence item (JSON array element, YAML block sequence item, CSV/PSV row or cell). | *** #### StructureKind [Section titled “StructureKind”](#structurekind) The kind of structural item found in source code. Categorizes top-level and nested declarations such as functions, classes, structs, enums, traits, and more. Use `Other` for language-specific constructs that do not fit a standard category. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-1) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | ---------------------------------------------------------------------------------------------- | | `Function` | A free-standing or associated function. | | `Method` | A method defined inside a class, struct, trait, or impl block. | | `Class` | A class definition. | | `Struct` | A struct definition. | | `Interface` | An interface or protocol definition. | | `Enum` | An enum definition. | | `Module` | A module or package declaration. | | `Trait` | A trait definition. | | `Impl` | An impl block (Rust) or similar implementation block. | | `Namespace` | A namespace declaration. | | `Other` | A language-specific construct that does not fit any standard category. — Fields: `0`: `String` | *** #### CommentKind [Section titled “CommentKind”](#commentkind) The kind of a comment found in source code. Distinguishes between single-line comments, block (multi-line) comments, and documentation comments. | Value | Description | | ------- | --------------------------------------------------------------------- | | `Line` | A single-line comment (e.g., `// ...` or `# ...`). | | `Block` | A block or multi-line comment using slash-star delimiters. | | `Doc` | A documentation comment such as `/// ...` or slash-double-star block. | *** #### DocstringFormat [Section titled “DocstringFormat”](#docstringformat) The format of a docstring extracted from source code. Identifies the docstring convention used, which varies by language (e.g., Python triple-quoted strings, JSDoc, Rustdoc `///` comments). ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-2) Unit variants serialize as a bare string (`"JSDoc"`); the `Other` variant serializes as a single-keyed object (`{"Other": "rst"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ------------------- | -------------------------------------------------------------------------------------------------- | | `PythonTripleQuote` | Python triple-quoted string docstring (`"""..."""`). | | `JsDoc` | JavaScript/TypeScript JSDoc block comment (opens with two stars, closes with star-slash). | | `Rustdoc` | Rust `///` or `//!` doc comment. | | `GoDoc` | Go doc comment (a comment block immediately preceding a declaration). | | `JavaDoc` | Java Javadoc block comment (opens with two stars, closes with star-slash). | | `Other` | A language-specific docstring format not covered by the standard variants. — Fields: `0`: `String` | *** #### ExportKind [Section titled “ExportKind”](#exportkind) The kind of an export statement found in source code. Covers named exports, default exports, and re-exports from other modules. | Value | Description | | ---------- | -------------------------------------------------------------------- | | `Named` | A named export (e.g., `export { foo }`). | | `Default` | A default export (e.g., `export default foo`). | | `ReExport` | A re-export from another module (e.g., `export { foo } from 'bar'`). | *** #### SymbolKind [Section titled “SymbolKind”](#symbolkind) The kind of a symbol definition found in source code. Categorizes symbol definitions such as variables, constants, functions, classes, types, interfaces, enums, and modules. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-3) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | --------------------------------------------------------------------------- | | `Variable` | A variable binding. | | `Constant` | A constant (immutable binding). | | `Function` | A function definition. | | `Class` | A class definition. | | `Type` | A type alias or typedef. | | `Interface` | An interface definition. | | `Enum` | An enum definition. | | `Module` | A module declaration. | | `Other` | A symbol kind not covered by the standard variants. — Fields: `0`: `String` | *** #### DiagnosticSeverity [Section titled “DiagnosticSeverity”](#diagnosticseverity) Severity level of a diagnostic produced during parsing. Used to classify parse errors, warnings, and informational messages found in the syntax tree. | Value | Description | | --------- | --------------------------------------------------------------- | | `Error` | A parse error (e.g., an `ERROR` or `MISSING` node in the tree). | | `Warning` | A warning-level diagnostic. | | `Info` | An informational diagnostic. | *** ### Errors [Section titled “Errors”](#errors) #### Error [Section titled “Error”](#error) Errors that can occur when using the tree-sitter language pack. Covers language lookup failures, parse errors, query errors, and I/O issues. Feature-gated variants are included when `config`, `download`, or related features are enabled. ##### Matching on `Error` [Section titled “Matching on Error”](#matching-on-error) The set of variants is not stable: new failure modes are added in minor releases, and `Io`, `Json`, and `Toml` exist only under certain feature combinations, so the variant set a downstream crate sees depends on which features it enables. Downstream `match`es must therefore carry a `_` arm; `#[non_exhaustive]` makes the compiler enforce that instead of letting a feature change silently break a build. ##### C ABI error codes [Section titled “C ABI error codes”](#c-abi-error-codes) Each variant alef can see carries an explicit `alef(error_code = N)` allocation that becomes a member of the generated `AlefFfiErrorCode` C enum. These numbers are a public ABI contract: **an allocated number is never reused after its variant is removed**, and a variant’s number never changes, because C callers compare against the value, not the name. New variants take the next free number. 0-4 are reserved by alef, so allocation starts at 100. An unannotated variant is emitted as the unknown code rather than as itself, which silently flattens the taxonomy — annotate every new variant. | Variant | Description | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `LanguageNotFound` | The requested language name (or alias) was not found in the registry. | | `DynamicLoad` | A dynamic shared library could not be loaded at runtime. | | `NullLanguagePointer` | The tree-sitter language function returned a null pointer for the given language name. | | `ParserSetup` | The language could not be applied to the parser (e.g., ABI version mismatch). | | `LockPoisoned` | An internal `RwLock` or `Mutex` was poisoned by a previous panic. | | `Config` | A configuration file or value was invalid or could not be applied. | | `ParseFailed` | The tree-sitter parser returned no tree for the given source input. | | `ParseTimeout` | The parse was cancelled because it exceeded its configured wall-clock budget. Raised only when a budget is configured — see `ProcessConfig.parse_timeout_ms`, which defaults to `null`. | | `QueryError` | A tree-sitter query could not be compiled or executed. | | `InvalidRange` | A byte range was invalid (e.g., end before start, or out of bounds). | | `Download` | A parser download from GitHub releases failed. | | `ChecksumMismatch` | The downloaded file’s SHA-256 digest did not match the manifest’s expected value. | | `CacheLock` | The cross-process download cache lock file could not be acquired or created. | *** # PHP API Reference ## PHP API Reference v1.16.1 [Section titled “PHP API Reference v1.16.1”](#php-api-reference-v1161) ### Functions [Section titled “Functions”](#functions) #### detectLanguageFromExtension() [Section titled “detectLanguageFromExtension()”](#detectlanguagefromextension) Detect language name from a file extension (without leading dot). Returns `null` for unrecognized extensions. The match is case-insensitive. **Signature:** ```php public static function detectLanguageFromExtension(string $ext): ?string ``` **Example:** ```php $result = detectLanguageFromExtension("value"); ``` **Parameters:** | Name | Type | Required | Description | | ----- | -------- | -------- | ----------- | | `ext` | `string` | Yes | The ext | **Returns:** `?string` *** #### detectLanguageFromPath() [Section titled “detectLanguageFromPath()”](#detectlanguagefrompath) Detect language name from a file path. Extracts the file extension and looks it up. Returns `null` if the path has no extension or the extension is not recognized. **Signature:** ```php public static function detectLanguageFromPath(string $path): ?string ``` **Example:** ```php $result = detectLanguageFromPath("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `path` | `string` | Yes | Path to the file | **Returns:** `?string` *** #### detectLanguageFromContent() [Section titled “detectLanguageFromContent()”](#detectlanguagefromcontent) Detect language name from file content using the shebang line (`#!`). Inspects only the first line of `content`. If it begins with `#!`, the interpreter name is extracted and mapped to a language name. Handles common patterns: * `#!/usr/bin/env python3` → `"python"` * `#!/bin/bash` → `"bash"` * `#!/usr/bin/env node` → `"javascript"` The `-S` flag accepted by some `env` implementations is skipped automatically. Version suffixes (e.g. `python3.11`, `ruby3.2`) are stripped before matching. A leading UTF-8 BOM (`U+FEFF`) is skipped before the `#!` check, so a BOM-prefixed script is still detected by its shebang. Returns `null` when content does not start with `#!` (after stripping a leading BOM), the shebang is malformed, or the interpreter is not recognised. **Signature:** ```php public static function detectLanguageFromContent(string $content): ?string ``` **Example:** ```php $result = detectLanguageFromContent("value"); ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ---------------------- | | `content` | `string` | Yes | The content to process | **Returns:** `?string` *** #### getHighlightsQuery() [Section titled “getHighlightsQuery()”](#gethighlightsquery) Get the highlights query for a language, if bundled. Returns the contents of `highlights.scm` as a static string, or `null` if no highlights query is bundled for this language. **Signature:** ```php public static function getHighlightsQuery(string $language): ?string ``` **Example:** ```php $result = getHighlightsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `?string` *** #### getInjectionsQuery() [Section titled “getInjectionsQuery()”](#getinjectionsquery) Get the injections query for a language, if bundled. Returns the contents of `injections.scm` as a static string, or `null` if no injections query is bundled for this language. **Signature:** ```php public static function getInjectionsQuery(string $language): ?string ``` **Example:** ```php $result = getInjectionsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `?string` *** #### getLocalsQuery() [Section titled “getLocalsQuery()”](#getlocalsquery) Get the locals query for a language, if bundled. Returns the contents of `locals.scm` as a static string, or `null` if no locals query is bundled for this language. **Signature:** ```php public static function getLocalsQuery(string $language): ?string ``` **Example:** ```php $result = getLocalsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `?string` *** #### getTagsQuery() [Section titled “getTagsQuery()”](#gettagsquery) Get the tags query for a language, if bundled. Returns the contents of `tags.scm` as a static string, or `null` if no tags query is bundled for this language. **Signature:** ```php public static function getTagsQuery(string $language): ?string ``` **Example:** ```php $result = getTagsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `?string` *** #### getIndentsQuery() [Section titled “getIndentsQuery()”](#getindentsquery) Get the indents query for a language, if bundled. Returns the contents of `indents.scm` (used for auto-indentation) as a static string, or `null` if no indents query is bundled for this language. **Signature:** ```php public static function getIndentsQuery(string $language): ?string ``` **Example:** ```php $result = getIndentsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `?string` *** #### getFoldsQuery() [Section titled “getFoldsQuery()”](#getfoldsquery) Get the folds query for a language, if bundled. Returns the contents of `folds.scm` (used for code folding) as a static string, or `null` if no folds query is bundled for this language. **Signature:** ```php public static function getFoldsQuery(string $language): ?string ``` **Example:** ```php $result = getFoldsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `?string` *** #### getLanguage() [Section titled “getLanguage()”](#getlanguage) Get a tree-sitter `Language` by name using the global registry. Resolves language aliases (e.g., `"shell"` maps to `"bash"`). When the `download` feature is enabled (default), automatically downloads the parser from GitHub releases if not found locally. **Errors:** Returns `Error::LanguageNotFound` if the language is not recognized, or `Error::Download` if auto-download fails. **Signature:** ```php public static function getLanguage(string $name): Language ``` **Example:** ```php $result = getLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `Language` **Errors:** Throws `Error`. *** #### getParser() [Section titled “getParser()”](#getparser) Get a `Parser` pre-configured for the given language. This is a convenience function that calls `get_language` and configures a new parser in one step. **Errors:** Returns `Error::LanguageNotFound` if the language is not recognized, or `Error::ParserSetup` if the language cannot be applied to the parser. **Signature:** ```php public static function getParser(string $name): Parser ``` **Example:** ```php $result = getParser("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `Parser` **Errors:** Throws `Error`. *** #### detectLanguage() [Section titled “detectLanguage()”](#detectlanguage) Detect language name from a file path or extension. This compatibility alias matches the pre-Alef Python binding API. **Signature:** ```php public static function detectLanguage(string $path): ?string ``` **Example:** ```php $result = detectLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `path` | `string` | Yes | Path to the file | **Returns:** `?string` *** #### availableLanguages() [Section titled “availableLanguages()”](#availablelanguages) List all available language names (sorted, deduplicated, includes aliases). Returns names of both statically compiled and dynamically loadable languages, plus any configured aliases. **Signature:** ```php public static function availableLanguages(): array ``` **Example:** ```php $result = availableLanguages(); ``` **Returns:** `array` *** #### hasLanguage() [Section titled “hasLanguage()”](#haslanguage) Check if a language is available by name or alias. Returns `true` if the language can be loaded (statically compiled, dynamically available, or a known alias for one of these). **Signature:** ```php public static function hasLanguage(string $name): bool ``` **Example:** ```php $result = hasLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `bool` *** #### languageCount() [Section titled “languageCount()”](#languagecount) Return the number of available languages. Includes statically compiled languages, dynamically loadable languages, and aliases. **Signature:** ```php public static function languageCount(): int ``` **Example:** ```php $result = languageCount(); ``` **Returns:** `int` *** #### process() [Section titled “process()”](#process) Process source code and extract file intelligence using the global registry. Parses the source with tree-sitter and extracts metrics, structure, imports, exports, comments, docstrings, symbols, diagnostics, and/or chunks based on the flags set in `ProcessConfig`. **Errors:** Returns `Error::InvalidRange` if the config carries a zero-valued limit or the source exceeds `ProcessConfig::max_source_bytes`, `Error::ParseTimeout` if the parse exceeds `ProcessConfig::parse_timeout_ms`, `Error::LanguageNotFound` if the language is unknown, or `Error::ParseFailed` if parsing yields no tree. **Signature:** ```php public static function process(string $source, ProcessConfig $config): ProcessResult ``` **Example:** ```php $result = process("value", new ProcessConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `string` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Throws `Error`. *** #### init() [Section titled “init()”](#init) Initialize the language pack with the given configuration. Applies any custom cache directory, then downloads all languages and groups specified in the config. This is the recommended entry point when you want to pre-warm the cache before use. **Errors:** Returns an error if configuration cannot be applied or if downloads fail. **Signature:** ```php public static function init(PackConfig $config): void ``` **Example:** ```php init(new PackConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Throws `Error`. *** #### configure() [Section titled “configure()”](#configure) Apply download configuration without downloading anything. Use this to set a custom cache directory before the first call to `get_language` or any download function. Changing the cache dir after languages have been registered has no effect on already-loaded languages. `PackConfig::cache_dir` is a BASE directory, not the final libs path: this crate appends `tree-sitter-language-pack/v{version}/libs` to it, the same suffix applied to the platform default cache directory. In the example below, files actually land under `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`, never directly in `/tmp/my-parsers/`. Call `cache_dir` to read back the resolved, fully-suffixed path. **Errors:** Returns an error if the lock cannot be acquired. **Signature:** ```php public static function configure(PackConfig $config): void ``` **Example:** ```php configure(new PackConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Throws `Error`. *** #### download() [Section titled “download()”](#download) Download specific languages to the local cache. Returns the number of distinct languages available after the call. Already compiled or cached languages are included in the count. Aliases are resolved before counting, so `["shell", "bash"]` names one language and returns 1. **Errors:** Returns an error if any language is not available in the manifest or if the download fails. **Signature:** ```php public static function download(array $names): int ``` **Example:** ```php $result = download([]); ``` **Parameters:** | Name | Type | Required | Description | | ------- | --------------- | -------- | ----------- | | `names` | `array` | Yes | The names | **Returns:** `int` **Errors:** Throws `Error`. *** #### prefetch() [Section titled “prefetch()”](#prefetch) Prefetch grammars: download any not already loadable from disk, then load every requested language into the process registry so a subsequent hot loop only parses. Unlike `download()`, this does not trust in-memory availability — it downloads whenever a grammar is not actually loadable from disk (fixing the case where a known-but-not-downloaded grammar is reported present), then resolves and caches every requested language. Call it once, up front, before a parallel workload. **Errors:** Returns `Error::Download` if a required grammar cannot be fetched, or `Error::LanguageNotFound` if a requested name is unknown. **Signature:** ```php public static function prefetch(array $languages): void ``` **Example:** ```php prefetch([]); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | --------------- | -------- | ------------- | | `languages` | `array` | Yes | The languages | **Returns:** No return value. **Errors:** Throws `Error`. *** #### downloadAll() [Section titled “downloadAll()”](#downloadall) Download all available languages from the remote manifest. Downloads the platform bundle and extracts every library it contains. Languages that appear in the manifest but are absent from the bundle (e.g. grammars that failed to compile at release time) are silently skipped — they are not treated as an error. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns an error if the manifest cannot be fetched or the bundle download fails. **Signature:** ```php public static function downloadAll(): int ``` **Example:** ```php $result = downloadAll(); ``` **Returns:** `int` **Errors:** Throws `Error`. *** #### downloadGroup() [Section titled “downloadGroup()”](#downloadgroup) Download every language in a named group. Groups are defined by the remote manifest, not by this library, and let you ensure a curated set of related grammars in one call instead of listing each name to `download()`. Already-cached languages are skipped. Call `manifest_groups` to discover the group names the manifest actually defines. The published manifest currently defines a single group, `"all"`; earlier revisions of this documentation advertised `"web"`, `"data"`, and `"systems"`, which the manifest has never contained, so every call following that example failed. Do not hardcode a group name without checking. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns `Error::Download` if the manifest cannot be fetched, if the group is unknown — the message lists the groups the manifest defines — or if any constituent language fails to download. **Signature:** ```php public static function downloadGroup(string $name): int ``` **Example:** ```php $result = downloadGroup("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `int` **Errors:** Throws `Error`. *** #### manifestLanguages() [Section titled “manifestLanguages()”](#manifestlanguages) Return all language names available in the remote manifest (371). Fetches (and caches) the remote manifest to discover the full list of downloadable languages. Use `downloaded_languages` to list what is already cached locally. **Errors:** Returns an error if the manifest cannot be fetched. **Signature:** ```php public static function manifestLanguages(): array ``` **Example:** ```php $result = manifestLanguages(); ``` **Returns:** `array` **Errors:** Throws `Error`. *** #### manifestGroups() [Section titled “manifestGroups()”](#manifestgroups) Return the names of every language group the remote manifest defines, sorted. Group names are manifest data, not a compile-time constant of this library, so this is the only reliable way to learn what `download_group` and `PackConfig::groups` accept. The published manifest currently defines just `"all"`. **Errors:** Returns `Error::Download` if the manifest cannot be fetched. **Signature:** ```php public static function manifestGroups(): array ``` **Example:** ```php $result = manifestGroups(); ``` **Returns:** `array` **Errors:** Throws `Error`. *** #### downloadedLanguages() [Section titled “downloadedLanguages()”](#downloadedlanguages) Return languages that are already downloaded and cached locally. Does not perform any network requests. Returns an empty list if the cache directory does not exist or cannot be read. **Signature:** ```php public static function downloadedLanguages(): array ``` **Example:** ```php $result = downloadedLanguages(); ``` **Returns:** `array` *** #### cleanCache() [Section titled “cleanCache()”](#cleancache) Delete all cached parser shared libraries. Resets the cache registration so the next call to `get_language` or a download function will re-register the (now empty) cache directory. **Errors:** Returns an error if the cache directory cannot be removed. **Signature:** ```php public static function cleanCache(): void ``` **Example:** ```php cleanCache(); ``` **Returns:** No return value. **Errors:** Throws `Error`. *** #### cacheDir() [Section titled “cacheDir()”](#cachedir) Return the effective cache directory path. This is `{base}/tree-sitter-language-pack/v{version}/libs/`, where `{base}` is either the custom BASE directory set via `configure` / `init` (`PackConfig::cache_dir`) or the platform default cache directory — both are suffixed identically, so a custom `cache_dir` is never used as the final libs path. The default resolves to `~/.cache/tree-sitter-language-pack/v{version}/libs/` on a typical Unix system. **Errors:** Returns an error if no cache directory can be resolved: `version` is somehow invalid, or (with no custom `cache_dir` configured) the platform reports none and `TREE_SITTER_LANGUAGE_PACK_CACHE_DIR` is unset. This crate no longer falls back to the temporary directory for the latter case — see #101 H2. **Signature:** ```php public static function cacheDir(): string ``` **Example:** ```php $result = cacheDir(); ``` **Returns:** `string` **Errors:** Throws `Error`. *** ### Types [Section titled “Types”](#types) #### ByteRange [Section titled “ByteRange”](#byterange) A byte range — start (inclusive) to end (exclusive). | Field | Type | Default | Description | | ------- | ----- | ------- | ---------------------------- | | `start` | `int` | — | Inclusive start byte offset. | | `end` | `int` | — | Exclusive end byte offset. | *** #### ChunkContext [Section titled “ChunkContext”](#chunkcontext) Metadata for a single chunk of source code. | Field | Type | Default | Description | | ---------------- | ---------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `language` | `string` | — | Language name used to parse this chunk. | | `chunkIndex` | `int` | — | Zero-indexed position of this chunk within the file’s chunk list. | | `totalChunks` | `int` | — | Total number of chunks the file was split into. | | `nodeTypes` | `array` | `[]` | Tree-sitter node kinds that appear at the top level of this chunk. | | `contextPath` | `array` | `[]` | Hierarchical path of enclosing structural items (e.g., `["MyClass", "my_method"]`). | | `symbolsDefined` | `array` | `[]` | Names of symbols defined within this chunk. | | `comments` | `array` | `[]` | Comments contained within this chunk. | | `docstrings` | `array` | `[]` | Docstrings contained within this chunk. Populated only for Python — the same language for which `ProcessResult::docstrings` is populated, and by the same classifier. Always empty for every other language. | | `hasErrorNodes` | `bool` | — | Whether this chunk contains any tree-sitter error nodes. | *** #### CodeChunk [Section titled “CodeChunk”](#codechunk) A chunk of source code with rich metadata. | Field | Type | Default | Description | | ----------- | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `content` | `string` | — | The raw source text of this chunk. | | `startByte` | `int` | — | Inclusive start byte offset of this chunk in the original source. | | `endByte` | `int` | — | Exclusive end byte offset of this chunk in the original source. | | `startLine` | `int` | — | Zero-indexed start line of this chunk. | | `endLine` | `int` | — | Zero-indexed row of the last byte actually included in this chunk (inclusive — the same row a `Span::end_line` would report for a node ending on that byte). Computed the same way regardless of whether the source has a trailing newline: it is always the row of `end_byte - 1`, never a phantom row past the file’s real content. | | `metadata` | `ChunkContext` | — | Contextual metadata about this chunk. | *** #### CommentInfo [Section titled “CommentInfo”](#commentinfo) A comment extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------- | ------------------- | ----------------------------------------------------------------- | | `text` | `string` | — | The raw text content of the comment. | | `kind` | `CommentKind` | `CommentKind::LINE` | The kind of comment (line, block, or doc). | | `span` | `Span` | — | Source span covering the comment. | | `associatedNode` | `?string` | `null` | Name of the syntax node this comment is directly associated with. | *** #### DataAttribute [Section titled “DataAttribute”](#dataattribute) An XML-style attribute attached to an `Element` node. Populated only for `DataNodeKind::Element`; always empty for `KeyValue` and `Sequence` nodes. | Field | Type | Default | Description | | ------- | -------- | ------- | --------------------------------------------------------------- | | `name` | `string` | — | Attribute name (e.g. `"class"`, `"href"`). | | `value` | `string` | — | Attribute value as a raw string (quotes stripped). | | `span` | `Span` | — | Source span covering the entire `name="value"` attribute token. | *** #### DataNode [Section titled “DataNode”](#datanode) A node in the hierarchical data tree produced by data-format extraction. When `ProcessConfig::data_extraction` is `true`, `ProcessResult::data` is populated with a root `DataNode` whose `children` mirror the structure of the parsed file. The `kind` field determines which other fields are meaningful: | `kind` | `key` | `value` | `attributes` | `children` | | ---------- | ------------------------- | ------------ | ------------ | -------------- | | `KeyValue` | key / mapping key / index | leaf value | empty | nested map | | `Element` | XML tag name | text content | XML attrs | child elements | | `Sequence` | positional index (`"0"`) | leaf value | empty | sub-items | | Field | Type | Default | Description | | ------------ | ---------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------- | | `kind` | `DataNodeKind` | `DataNodeKind::KEYVALUE` | Whether this node is a key/value pair, XML element, or sequence item. | | `key` | `?string` | `null` | Key, attribute name, tag name, or positional index (`"0"`, `"1"`, …). `null` at the document root. | | `value` | `?string` | `null` | Leaf scalar value, if any. `null` for containers (objects, arrays, XML elements with child elements). | | `attributes` | `array` | `[]` | Attributes on element-shape nodes (XML `STag` attributes). Empty for all other kinds. | | `children` | `array` | `[]` | Children for nested containers and XML element bodies. | | `span` | `Span` | — | Source span covering this node in the original source file. | *** #### Diagnostic [Section titled “Diagnostic”](#diagnostic) A diagnostic (syntax error, missing node, etc.) from parsing. | Field | Type | Default | Description | | ---------- | -------------------- | --------------------------- | ---------------------------------------------- | | `message` | `string` | — | Human-readable description of the diagnostic. | | `severity` | `DiagnosticSeverity` | `DiagnosticSeverity::ERROR` | Severity of the diagnostic. | | `span` | `Span` | — | Source span where the diagnostic was detected. | *** #### DocSection [Section titled “DocSection”](#docsection) A section within a docstring (e.g., Args, Returns, Raises). | Field | Type | Default | Description | | ------------- | --------- | ------- | ------------------------------------------------------- | | `kind` | `string` | — | Section kind (e.g., `"args"`, `"returns"`, `"raises"`). | | `name` | `?string` | `null` | Parameter or return value name, if applicable. | | `description` | `string` | — | Description text for this section. | *** #### DocstringInfo [Section titled “DocstringInfo”](#docstringinfo) A docstring extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | `string` | — | The raw text of the docstring. | | `format` | `DocstringFormat` | `DocstringFormat::PYTHONTRIPLEQUOTE` | The docstring format (Python, JSDoc, Rustdoc, etc.). | | `span` | `Span` | — | Source span covering the docstring. | | `associatedItem` | `?string` | `null` | Name of the item this docstring documents. | | `parsedSections` | `array` | `[]` | Parsed sections of the docstring (Args, Returns, Raises, etc.). **Reserved: not yet populated.** Always empty, for every `DocstringFormat`. Parsing a docstring body into sections requires implementing each convention’s own layout (Google/NumPy/reST style for Python, `@param`/`@returns` for JSDoc/Javadoc, and so on), which no extractor here does yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | *** #### DownloadManager [Section titled “DownloadManager”](#downloadmanager) Manages downloading and caching of pre-built parser shared libraries. ##### Methods [Section titled “Methods”](#methods) ###### new() [Section titled “new()”](#new) Create a new download manager for the given version. **Errors:** Returns `Error::Download` if `version` is empty, contains a path separator or `..`, or contains a character outside `[A-Za-z0-9.+-]` — see `validate_version` — or if no cache directory can be resolved (see `Self::default_cache_dir`). **Signature:** ```php public static function new(string $version): DownloadManager ``` **Example:** ```php $result = DownloadManager::new("value"); ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ----------- | | `version` | `string` | Yes | The version | **Returns:** `DownloadManager` **Errors:** Throws `Error`. ###### installedLanguages() [Section titled “installedLanguages()”](#installedlanguages) List languages that are already downloaded and cached. Derived from the on-disk cache filenames, one canonical name per file, plus every alias that resolves to it (via `aliases_for`) — so this list agrees with the user-facing `LanguageRegistry::available_languages` about which names are “available”; both report `"shell"` once `bash` is cached, for example. A previous version reported canonical names only, which could never agree with `available_languages()`. See #107. Returns an empty list if the cache directory does not exist. If it exists but cannot be read (e.g. a permission error), also returns an empty list — changing this to a `Result` would be a breaking change across every language binding — but logs a `tracing::warn!` so the failure is not silently indistinguishable from “nothing installed”. **Signature:** ```php public function installedLanguages(): array ``` **Example:** ```php $result = $instance->installedLanguages(); ``` **Returns:** `array` ###### downloadAllBestEffort() [Section titled “downloadAllBestEffort()”](#downloadallbesteffort) Download the platform bundle and extract every library file it contains. Unlike `Self::ensure_languages`, this does not check the manifest language list against archive contents — it simply extracts all `.so`/`.dylib`/`.dll` files from the bundle. Languages in the manifest that are missing from the archive are silently ignored rather than returning an error. Returns the number of library files extracted (including those already cached). **Signature:** ```php public function downloadAllBestEffort(): int ``` **Example:** ```php $result = $instance->downloadAllBestEffort(); ``` **Returns:** `int` **Errors:** Throws `Error`. ###### cleanCache() [Section titled “cleanCache()”](#cleancache-1) Remove all cached parser libraries. Acquires the cross-process lock so `clean_cache` cannot race a concurrent downloader (avoids Windows sharing-violation errors against an in-flight bundle write). The `.download.lock` file itself is **not** removed — it is permanent infrastructure; deleting it could allow a concurrent process that already opened the file to continue holding a stale lock handle while a new process opens a fresh inode, breaking the mutual-exclusion guarantee. **Signature:** ```php public function cleanCache(): void ``` **Example:** ```php $instance->cleanCache(); ``` **Returns:** No return value. **Errors:** Throws `Error`. *** #### ExportInfo [Section titled “ExportInfo”](#exportinfo) An export statement extracted from source code. | Field | Type | Default | Description | | ------ | ------------ | ------------------- | -------------------------------------------------- | | `name` | `string` | — | The exported name. | | `kind` | `ExportKind` | `ExportKind::NAMED` | The kind of export (named, default, or re-export). | | `span` | `Span` | — | Source span covering the export statement. | *** #### FileMetrics [Section titled “FileMetrics”](#filemetrics) Aggregate metrics for a source file. | Field | Type | Default | Description | | -------------- | ----- | ------- | -------------------------------------------------------------- | | `totalLines` | `int` | — | Total number of lines (including blank and comment lines). | | `codeLines` | `int` | — | Number of lines containing non-blank, non-comment source code. | | `commentLines` | `int` | — | Number of lines that are entirely comments. | | `blankLines` | `int` | — | Number of blank (whitespace-only) lines. | | `totalBytes` | `int` | — | Total byte length of the source file. | | `nodeCount` | `int` | — | Total number of nodes in the syntax tree. | | `errorCount` | `int` | — | Number of error nodes in the syntax tree (parse errors). | | `maxDepth` | `int` | — | Maximum nesting depth reached in the syntax tree. | *** #### ImportInfo [Section titled “ImportInfo”](#importinfo) An import statement extracted from source code. | Field | Type | Default | Description | | ------------ | --------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `source` | `string` | — | The module or path being imported from. | | `items` | `array` | `[]` | Specific names imported from the source module. For `import a, b` / `from m import a, b`, every entry’s base name (never the alias). For a JavaScript/TypeScript named-imports clause (`import { a, b as c } from 'm'`), every specifier’s original name. Populated for Python and JavaScript/TypeScript only. Always empty for every other language this library recognises import statements for — Rust, Go, Java, Kotlin, and Elixir (`import`/`alias`/`require`/`use`) — and for a JS/TS namespace import (`import * as ns`) or default import (`import x from 'm'`), neither of which names individual items. | | `alias` | `?string` | `null` | Alias assigned to the import (e.g., `import numpy as np`). Populated for Python’s single-name form (`import numpy as np`, `from m import a as b`) and JavaScript/TypeScript’s namespace form (`import * as ns from 'm'`) or a named-imports clause naming exactly one specifier (`import { a as b } from 'm'`). `null` for Rust, Go, Java, Kotlin, and Elixir (which has its own `as:` alias option on `alias` directives, not yet extracted here) — and for a Python statement that aliases several names at once (`import os, sys as s`), where there is no single alias to report for the statement as a whole, so only `items` is populated for it. | | `isWildcard` | `bool` | — | Whether this is a wildcard import (e.g., `import *` or `use foo::*`). Detected from the syntax tree — a dedicated wildcard node (`wildcard_import` in Python, `use_wildcard` in Rust) or a bare `*` token outside of string-literal content — not by searching the import’s source text for a `*` character, so a glob in an import path string (`import a from './glob*.js'`) is not mistaken for one. | | `span` | `Span` | — | Source span covering the import statement. | *** #### Language [Section titled “Language”](#language) *** #### LanguageRegistry [Section titled “LanguageRegistry”](#languageregistry) Thread-safe registry of tree-sitter language parsers. Manages both statically compiled and dynamically loaded language grammars. Use `LanguageRegistry::new()` for the default registry, or access the global instance via the module-level convenience functions (`get_language`, `available_languages`, etc.). ##### Methods [Section titled “Methods”](#methods-1) ###### new() [Section titled “new()”](#new-1) Create a new registry populated with all statically compiled languages. When the `dynamic-loading` feature is enabled, the registry also knows about dynamically loadable grammars and will load them on demand. **Signature:** ```php public static function new(): LanguageRegistry ``` **Example:** ```php $result = LanguageRegistry::new(); ``` **Returns:** `LanguageRegistry` ###### getLanguage() [Section titled “getLanguage()”](#getlanguage-1) Get a tree-sitter `Language` by name. Resolves aliases (e.g., `"shell"` -> `"bash"`, `"makefile"` -> `"make"`), then looks up the language in the static table. When the `dynamic-loading` feature is enabled, falls back to loading a shared library on demand. **Errors:** Returns `Error::LanguageNotFound` if the name (after alias resolution) does not match any known grammar. **Signature:** ```php public function getLanguage(string $name): Language ``` **Example:** ```php $result = $instance->getLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `Language` **Errors:** Throws `Error`. ###### availableLanguages() [Section titled “availableLanguages()”](#availablelanguages-1) List all available language names, sorted and deduplicated. Includes statically compiled languages, dynamically loadable languages (if the `dynamic-loading` feature is enabled), and all configured aliases. **Signature:** ```php public function availableLanguages(): array ``` **Example:** ```php $result = $instance->availableLanguages(); ``` **Returns:** `array` ###### hasParser() [Section titled “hasParser()”](#hasparser) Check whether this language can be parsed right now, without downloading. Resolves aliases, then answers from exactly the lookup `get_language` performs: the statically compiled table, the already-loaded dynamic grammars, and the parser shared libraries present in the primary and extra (download-cache) library directories. It never performs network I/O. A previous implementation consulted only the statically compiled table. That table is empty in every build that does not set `TSLP_LANGUAGES`, so the function answered `false` for languages this registry parses perfectly well. Contrast `has_language`, which is also `true` for a grammar that is merely *known to the manifest* and would have to be downloaded first. The pair distinguishes “we can parse it offline, now” from “we recognise the name”. The first `true` answer for a dynamic grammar loads its shared library: loading is the only way to know the grammar is usable, since a truncated or wrong-architecture library exists on disk but cannot parse. Loads are cached process-wide, so repeat calls are cheap. **Signature:** ```php public function hasParser(string $name): bool ``` **Example:** ```php $result = $instance->hasParser("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `bool` ###### hasLanguage() [Section titled “hasLanguage()”](#haslanguage-1) Check whether a language is available by name or alias. Returns `true` if the language can be loaded, either from the static table or from a dynamic library on disk. Every branch is one more way to answer `true`, so they are ordered cheapest-first and the filesystem is only consulted once every in-memory source has said no. Probing the loaded-grammar map and the manifest ahead of the `stat` calls is what keeps this off the syscall path for the languages a process actually uses. **Signature:** ```php public function hasLanguage(string $name): bool ``` **Example:** ```php $result = $instance->hasLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `bool` ###### languageCount() [Section titled “languageCount()”](#languagecount-1) Return the total number of available languages (including aliases). Counts the same set `available_languages` lists, without materialising or sorting it. **Signature:** ```php public function languageCount(): int ``` **Example:** ```php $result = $instance->languageCount(); ``` **Returns:** `int` ###### process() [Section titled “process()”](#process-1) Parse source code and extract file intelligence based on config in a single pass. **Errors:** Returns `Error::InvalidRange` if the config is invalid (see `ProcessConfig::validate`) or if the source exceeds the configured `max_source_bytes`; `Error::LanguageNotFound` if the language is unknown; or `Error::ParseFailed` if parsing produces no tree. **Signature:** ```php public function process(string $source, ProcessConfig $config): ProcessResult ``` **Example:** ```php $result = $instance->process("value", new ProcessConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `string` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Throws `Error`. *** #### Node [Section titled “Node”](#node) A single syntax node within a `Tree`. Nodes hold a strong reference to their parent tree so they remain valid regardless of how the tree is moved or stored at the FFI boundary. ##### Methods [Section titled “Methods”](#methods-2) ###### kind() [Section titled “kind()”](#kind) Return the node’s kind name (e.g. `"function_definition"`). **Signature:** ```php public function kind(): string ``` **Example:** ```php $result = $instance->kind(); ``` **Returns:** `string` ###### kindId() [Section titled “kindId()”](#kindid) Return the node’s numeric kind ID. Tree-sitter assigns a stable `u16` ID to every node kind in a grammar (e.g. `"function_definition" → 42`). Comparing `kind_id()` is cheaper than comparing the string `kind()` in tight AST loops. **Signature:** ```php public function kindId(): int ``` **Example:** ```php $result = $instance->kindId(); ``` **Returns:** `int` ###### startByte() [Section titled “startByte()”](#startbyte) Return the inclusive start byte offset of this node. **Signature:** ```php public function startByte(): int ``` **Example:** ```php $result = $instance->startByte(); ``` **Returns:** `int` ###### endByte() [Section titled “endByte()”](#endbyte) Return the exclusive end byte offset of this node. **Signature:** ```php public function endByte(): int ``` **Example:** ```php $result = $instance->endByte(); ``` **Returns:** `int` ###### byteRange() [Section titled “byteRange()”](#byterange-1) Return the node’s byte range as a `ByteRange`. Callers should slice their own source bytes — this is a zero-copy text accessor. **Signature:** ```php public function byteRange(): ByteRange ``` **Example:** ```php $result = $instance->byteRange(); ``` **Returns:** `ByteRange` ###### startPosition() [Section titled “startPosition()”](#startposition) Return the start `Point` (row, column). **Signature:** ```php public function startPosition(): Point ``` **Example:** ```php $result = $instance->startPosition(); ``` **Returns:** `Point` ###### endPosition() [Section titled “endPosition()”](#endposition) Return the end `Point` (row, column). **Signature:** ```php public function endPosition(): Point ``` **Example:** ```php $result = $instance->endPosition(); ``` **Returns:** `Point` ###### isNamed() [Section titled “isNamed()”](#isnamed) True when this node is named (not punctuation/whitespace). **Signature:** ```php public function isNamed(): bool ``` **Example:** ```php $result = $instance->isNamed(); ``` **Returns:** `bool` ###### isError() [Section titled “isError()”](#iserror) True when this is an error node. **Signature:** ```php public function isError(): bool ``` **Example:** ```php $result = $instance->isError(); ``` **Returns:** `bool` ###### isMissing() [Section titled “isMissing()”](#ismissing) True when this is a missing-token node. **Signature:** ```php public function isMissing(): bool ``` **Example:** ```php $result = $instance->isMissing(); ``` **Returns:** `bool` ###### isExtra() [Section titled “isExtra()”](#isextra) True when this is an “extra” node (e.g. a comment). **Signature:** ```php public function isExtra(): bool ``` **Example:** ```php $result = $instance->isExtra(); ``` **Returns:** `bool` ###### hasError() [Section titled “hasError()”](#haserror) True when this node or any descendant is an error. **Signature:** ```php public function hasError(): bool ``` **Example:** ```php $result = $instance->hasError(); ``` **Returns:** `bool` ###### parent() [Section titled “parent()”](#parent) Return this node’s parent, if any. **Signature:** ```php public function parent(): ?Node ``` **Example:** ```php $result = $instance->parent(); ``` **Returns:** `?Node` ###### child() [Section titled “child()”](#child) Return the i-th child of this node, if any. **Signature:** ```php public function child(int $index): ?Node ``` **Example:** ```php $result = $instance->child(42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | ----- | -------- | ----------- | | `index` | `int` | Yes | The index | **Returns:** `?Node` ###### childCount() [Section titled “childCount()”](#childcount) Total number of children (including unnamed). **Signature:** ```php public function childCount(): int ``` **Example:** ```php $result = $instance->childCount(); ``` **Returns:** `int` ###### namedChild() [Section titled “namedChild()”](#namedchild) Return the i-th named child of this node, if any. **Signature:** ```php public function namedChild(int $index): ?Node ``` **Example:** ```php $result = $instance->namedChild(42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | ----- | -------- | ----------- | | `index` | `int` | Yes | The index | **Returns:** `?Node` ###### namedChildCount() [Section titled “namedChildCount()”](#namedchildcount) Number of named children of this node. **Signature:** ```php public function namedChildCount(): int ``` **Example:** ```php $result = $instance->namedChildCount(); ``` **Returns:** `int` ###### childByFieldName() [Section titled “childByFieldName()”](#childbyfieldname) Look up a child by its grammar-defined field name. **Signature:** ```php public function childByFieldName(string $name): ?Node ``` **Example:** ```php $result = $instance->childByFieldName("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `?Node` ###### toSexp() [Section titled “toSexp()”](#tosexp) Return the S-expression form of this node’s subtree. **Signature:** ```php public function toSexp(): string ``` **Example:** ```php $result = $instance->toSexp(); ``` **Returns:** `string` ###### walk() [Section titled “walk()”](#walk) Return a `TreeCursor` positioned at this node. **Signature:** ```php public function walk(): TreeCursor ``` **Example:** ```php $result = $instance->walk(); ``` **Returns:** `TreeCursor` *** #### PackConfig [Section titled “PackConfig”](#packconfig) Configuration for the tree-sitter language pack. Controls cache directory and which languages to pre-download. Can be loaded from a TOML file, constructed programmatically, or passed as a dict/object from language bindings. | Field | Type | Default | Description | | ----------- | ---------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cacheDir` | `?string` | `null` | Override the BASE directory the parser cache lives under. This is a base, not the final library path: the crate appends `tree-sitter-language-pack/v{version}/libs` to it, exactly as it does to the platform default. So `cache_dir = "/tmp/my-parsers"` resolves to `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`. The suffix is not cosmetic. It keeps the whole cache tree — manifest, bundles and lock file included — inside a directory this library owns and versions. Earlier releases used this path verbatim, which put those files in the configured directory’s PARENT and let a cache built by one crate version be reused by another. Default base: the platform cache dir, e.g. `~/.cache` on Linux. | | `languages` | `?array` | `[]` | Languages to pre-download on init. Each entry is a language name (e.g. `"python"`, `"rust"`). | | `groups` | `?array` | `[]` | Language groups to pre-download. Group names come from the remote manifest, so the valid set is not fixed by this library; the published manifest currently defines only `"all"`. Call `manifest_groups` to enumerate them. An unknown name makes `init` fail. | *** #### Parser [Section titled “Parser”](#parser) A tree-sitter parser configured for one language at a time. ##### Methods [Section titled “Methods”](#methods-3) ###### new() [Section titled “new()”](#new-2) Construct a new parser with no language set and no parse limits. Call `Parser::set_language` before parsing. Limits are opt-in via `set_max_source_bytes` and `set_parse_timeout_ms`; both default to unbounded so that existing callers are unaffected. **Signature:** ```php public static function new(): Parser ``` **Example:** ```php $result = Parser::new(); ``` **Returns:** `Parser` ###### setMaxSourceBytes() [Section titled “setMaxSourceBytes()”](#setmaxsourcebytes) Refuse to parse sources longer than `max_bytes`. `null` (the default) means no limit. Over-limit input makes `parse` and `parse_bytes` return `null` after emitting a `WARN`; input is never silently truncated. See `RECOMMENDED_MAX_SOURCE_BYTES`. **Signature:** ```php public function setMaxSourceBytes(int $maxBytes): void ``` **Example:** ```php $instance->setMaxSourceBytes(42); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------ | -------- | ------------- | | `maxBytes` | `?int` | No | The max bytes | **Returns:** No return value. ###### setParseTimeoutMs() [Section titled “setParseTimeoutMs()”](#setparsetimeoutms) Cancel a parse that exceeds `timeout_ms` milliseconds of wall clock. `null` (the default) means no budget. Cancellation runs through tree-sitter’s parse progress callback, so it is granular to that callback’s interval rather than exact. See `RECOMMENDED_PARSE_TIMEOUT_MS`. **Signature:** ```php public function setParseTimeoutMs(int $timeoutMs): void ``` **Example:** ```php $instance->setParseTimeoutMs(42); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | ------ | -------- | -------------- | | `timeoutMs` | `?int` | No | The timeout ms | **Returns:** No return value. ###### setLanguage() [Section titled “setLanguage()”](#setlanguage) Configure the parser to use the language identified by name (e.g. `"python"`). Resolves the language through the global registry — auto-downloading if necessary, when the `download` feature is enabled. **Errors:** Returns `Error::LanguageNotFound` if the language is not recognized, or `Error::ParserSetup` if the language ABI is incompatible. **Signature:** ```php public function setLanguage(string $name): void ``` **Example:** ```php $instance->setLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** No return value. **Errors:** Throws `Error`. ###### parse() [Section titled “parse()”](#parse) Parse a UTF-8 source string. Returns `null` if no language is set, if the parse was cancelled by the configured timeout, or if the source exceeds the configured size limit. Each non-parse outcome is logged, so an empty result is never silent. ###### Concurrency [Section titled “Concurrency”](#concurrency) Parsing runs fully in parallel across threads for almost every language — no lock is taken. The exception is the small set of grammars whose external scanner keeps mutable process-global state (currently just `properties`): parses of that language are serialized against each other through an internal per-language lock, so that concurrent threads can’t corrupt shared scanner state. Every other language is unaffected by that lock and never waits on it. **Signature:** ```php public function parse(string $source): ?Tree ``` **Example:** ```php $result = $instance->parse("value"); ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------- | -------- | ----------- | | `source` | `string` | Yes | The source | **Returns:** `?Tree` ###### parseBytes() [Section titled “parseBytes()”](#parsebytes) Parse a raw byte slice. Same outcomes as `parse`, including the concurrency behaviour documented there. **Signature:** ```php public function parseBytes(string $source): ?Tree ``` **Example:** ```php $result = $instance->parseBytes("data"); ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------- | -------- | ----------- | | `source` | `string` | Yes | The source | **Returns:** `?Tree` ###### reset() [Section titled “reset()”](#reset) Reset internal state. The next call to `parse` will not be incremental. **Signature:** ```php public function reset(): void ``` **Example:** ```php $instance->reset(); ``` **Returns:** No return value. *** #### Point [Section titled “Point”](#point) A source position — row + column, zero-indexed. | Field | Type | Default | Description | | -------- | ----- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `row` | `int` | — | Zero-indexed row number. | | `column` | `int` | — | Zero-indexed column, counted in **bytes** from the start of the row. This is `tree_sitter::Point::column` verbatim, and tree-sitter defines it as a byte offset — not characters, and not UTF-16 code units. Measured on a row of the form `x = ''` where `` is a single 4-byte character (an emoji), the string node reports columns `4..10`, identical to its byte range; the character columns would be `4..7` and the UTF-16 columns `4..8`. Anything that builds LSP positions (UTF-16) or editor caret columns (characters) from this field is silently wrong on every row containing a non-ASCII byte, and must re-measure the row against the source text instead. Earlier releases documented this field as UTF-16 code units; that was never what the value contained. | *** #### ProcessConfig [Section titled “ProcessConfig”](#processconfig) Configuration for the `process()` function. Controls which analysis features are enabled and whether chunking is performed. | Field | Type | Default | Description | | ---------------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `language` | `string` | `""` | Language name (required). | | `structure` | `bool` | `true` | Extract structural items (functions, classes, etc.). Default: true. | | `imports` | `bool` | `true` | Extract import statements. Default: true. | | `exports` | `bool` | `true` | Extract export statements. Default: true. | | `comments` | `bool` | `false` | Extract comments. Default: false. | | `docstrings` | `bool` | `false` | Extract docstrings. Default: false. | | `symbols` | `bool` | `false` | Extract symbol definitions. Default: false. | | `diagnostics` | `bool` | `false` | Include parse diagnostics. Default: false. | | `chunkMaxSize` | `?int` | `null` | Maximum chunk size in bytes. `null` disables chunking. `Some(0)` is rejected by `ProcessConfig::validate` with `Error::InvalidRange`. A zero-sized chunk limit previously produced an empty chunk list and silently discarded the whole source; use `null` to mean “do not chunk”. | | `dataExtraction` | `bool` | `false` | Extract hierarchical key/value data tree from data-format files. Default: false. When `true`, `ProcessResult::data` is populated with a `DataNode` tree for supported languages: JSON, YAML, TOML, `.properties`, HCL/HOCON, INI, editorconfig, KDL, CUE, CSV, PSV, PO, nginx config, Caddy config, XML, and DTD. For languages outside this set the field is left as `null`. | | `maxSourceBytes` | `?int` | `null` | Reject source longer than this many bytes instead of parsing it. Default: `null` (unbounded). Tree-sitter allocates and walks proportionally to input size, so an unbounded parse of attacker-supplied input is a denial-of-service vector. The default stays unbounded for backward compatibility; services handling untrusted input should opt in, e.g. with `RECOMMENDED_MAX_SOURCE_BYTES`. Exceeding the limit fails the call with `Error::InvalidRange` — the source is never silently truncated. | | `parseTimeoutMs` | `?int` | `null` | Wall-clock budget for the parse step, in milliseconds. Default: `null` (no timeout). Enforced through tree-sitter’s parse progress callback, which the parser invokes periodically; cancellation is therefore granular to that callback interval rather than exact. A parse that exceeds the budget fails with `Error::ParseTimeout`. | *** #### ProcessResult [Section titled “ProcessResult”](#processresult) Complete analysis result from processing a source file. Contains metrics, structural analysis, imports/exports, comments, docstrings, symbols, diagnostics, and optionally chunked code segments. Fields are populated based on the `ProcessConfig` flags. | Field | Type | Default | Description | | ------------- | ---------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `string` | — | The language name used to parse the source file. | | `metrics` | `FileMetrics` | — | File-level metrics (line counts, byte size, error count). | | `structure` | `array` | `[]` | Top-level structural items (functions, classes, etc.). | | `imports` | `array` | `[]` | Import statements extracted from the source. | | `exports` | `array` | `[]` | Export statements extracted from the source. | | `comments` | `array` | `[]` | Comments extracted from the source. | | `docstrings` | `array` | `[]` | Docstrings extracted from the source. | | `symbols` | `array` | `[]` | Symbol definitions (variables, types, functions) extracted from the source. | | `diagnostics` | `array` | `[]` | Parse diagnostics (syntax errors, missing nodes) from tree-sitter. | | `chunks` | `array` | `[]` | Syntax-aware code chunks produced when chunking is enabled. | | `data` | `?DataNode` | `null` | Hierarchical data tree extracted when `config.data_extraction` is `true`. Populated for supported data-format languages (JSON, YAML, TOML, properties, HCL, INI, XML, CSV, and more). `null` when `data_extraction` is `false` (the default) or when the language is not a recognised data format. See `DataNode` for the shape of the returned tree. | *** #### Span [Section titled “Span”](#span) Byte and line/column range in source code. Represents both byte offsets (for slicing) and human-readable line/column positions (for display and diagnostics). | Field | Type | Default | Description | | ------------- | ----- | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `startByte` | `int` | — | Inclusive start byte offset in the source. | | `endByte` | `int` | — | Exclusive end byte offset in the source. | | `startLine` | `int` | — | Zero-indexed line number of the span’s start. | | `startColumn` | `int` | — | Zero-indexed column of the span’s start, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | | `endLine` | `int` | — | Zero-indexed line number of the span’s end. | | `endColumn` | `int` | — | Zero-indexed column of the span’s end, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | *** #### StructureItem [Section titled “StructureItem”](#structureitem) A structural item (function, class, struct, etc.) in source code. | Field | Type | Default | Description | | ------------ | ---------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `kind` | `StructureKind` | `StructureKind::FUNCTION` | The kind of structural item. | | `name` | `?string` | `null` | The declared name of the item, if present. | | `visibility` | `?string` | `null` | Visibility modifier (e.g., `"pub"`, `"public"`, `"private"`). | | `span` | `Span` | — | Source span covering the entire item declaration. | | `children` | `array` | `[]` | Nested structural items (e.g., methods within a class). | | `decorators` | `array` | `[]` | Decorator or attribute names applied to the item. **Reserved: not yet populated.** Always empty, for every language. Recognising a decorator requires per-language grammar knowledge (a Python `decorated_definition` wrapper, Java/C# annotations, Rust attributes each have a different shape), which no extractor here implements yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | | `docComment` | `?string` | `null` | Documentation comment attached to the item, if any. The text of the comment (or run of comments) immediately preceding the item, with no blank line in between, when that comment is classified as a doc comment. Multiple adjacent single-line doc comments (Rust `///`) are joined with `\n` in source order. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`). `null` for every other language, and for a preceding comment that is not in doc-comment form (a plain `#` comment in Python, Ruby, or Elixir) — Python’s docstring convention is captured separately, as `DocstringInfo`, not through this field. | | `signature` | `?string` | `null` | Full signature text of the item (e.g., function parameters and return type). The item’s own source text from its start up to the start of its body (see `StructureItem::body_span`), trimmed of trailing whitespace — for example `fn add(a: i32, b: i32) -> i32` for a Rust function whose body is `{ a + b }`. `null` only when that text is empty, which does not happen for any item `StructureKind` currently reports. Populated for every language and kind this library extracts structure for, since it is derived from `body_span`’s boundary rather than per-language syntax. | | `bodySpan` | `?Span` | `null` | Source span covering only the body of the item, if distinct from the declaration. | *** #### SymbolInfo [Section titled “SymbolInfo”](#symbolinfo) A symbol (variable, function, type, etc.) extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------ | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `string` | — | The name of the symbol. | | `kind` | `SymbolKind` | `SymbolKind::VARIABLE` | The kind of symbol (variable, function, class, etc.). | | `span` | `Span` | — | Source span covering the symbol definition. | | `typeAnnotation` | `?string` | `null` | Explicit type annotation, if present in the source. | | `doc` | `?string` | `null` | Documentation comment immediately preceding this symbol, resolved by the same walk `StructureItem::doc_comment` uses (see `doc_comment_at`) — never hard-coded `null`. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`) — the languages whose comment classification recognizes a doc-kind comment. `null` for every other language (e.g. Python, Go, Ruby, which have no doc-kind comment classification), and also `null` when a symbol in a supported language simply has no doc comment immediately above it. | *** #### Tree [Section titled “Tree”](#tree) A parsed syntax tree. Cheap to clone (refcount bump). ##### Methods [Section titled “Methods”](#methods-4) ###### rootNode() [Section titled “rootNode()”](#rootnode) Return the root `Node` of this tree. **Signature:** ```php public function rootNode(): Node ``` **Example:** ```php $result = $instance->rootNode(); ``` **Returns:** `Node` ###### walk() [Section titled “walk()”](#walk-1) Return a `TreeCursor` positioned at the root. **Signature:** ```php public function walk(): TreeCursor ``` **Example:** ```php $result = $instance->walk(); ``` **Returns:** `TreeCursor` *** #### TreeCursor [Section titled “TreeCursor”](#treecursor) A cursor for traversing a `Tree`. ##### Methods [Section titled “Methods”](#methods-5) ###### node() [Section titled “node()”](#node-1) Return the `Node` at the cursor’s current position. **Signature:** ```php public function node(): Node ``` **Example:** ```php $result = $instance->node(); ``` **Returns:** `Node` ###### gotoFirstChild() [Section titled “gotoFirstChild()”](#gotofirstchild) Move the cursor to the first child of the current node. Returns `true` if a child existed. **Signature:** ```php public function gotoFirstChild(): bool ``` **Example:** ```php $result = $instance->gotoFirstChild(); ``` **Returns:** `bool` ###### gotoParent() [Section titled “gotoParent()”](#gotoparent) Move the cursor to the parent of the current node. Returns `true` if a parent existed. **Signature:** ```php public function gotoParent(): bool ``` **Example:** ```php $result = $instance->gotoParent(); ``` **Returns:** `bool` ###### gotoNextSibling() [Section titled “gotoNextSibling()”](#gotonextsibling) Move the cursor to the next sibling of the current node. Returns `true` if a sibling existed. **Signature:** ```php public function gotoNextSibling(): bool ``` **Example:** ```php $result = $instance->gotoNextSibling(); ``` **Returns:** `bool` ###### fieldName() [Section titled “fieldName()”](#fieldname) Return the field name for the current node, if any. **Signature:** ```php public function fieldName(): ?string ``` **Example:** ```php $result = $instance->fieldName(); ``` **Returns:** `?string` *** ### Enums [Section titled “Enums”](#enums) #### DataNodeKind [Section titled “DataNodeKind”](#datanodekind) The kind of a data node extracted from a data-format file. Classifies each node in the hierarchical `DataNode` tree returned when `data_extraction` is enabled on `ProcessConfig`. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract) Unit variants serialize as a bare string (`"KeyValue"`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ---------- | -------------------------------------------------------------------------------------------------------------------- | | `KeyValue` | A key/value pair or mapping (json/toml/properties/yaml/hcl/cue/kdl pair, or a wrapper “object”/“mapping” container). | | `Element` | An XML element with a tag name in `key` and attributes in `attributes`. | | `Sequence` | A positional sequence item (JSON array element, YAML block sequence item, CSV/PSV row or cell). | *** #### StructureKind [Section titled “StructureKind”](#structurekind) The kind of structural item found in source code. Categorizes top-level and nested declarations such as functions, classes, structs, enums, traits, and more. Use `Other` for language-specific constructs that do not fit a standard category. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-1) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | ---------------------------------------------------------------------------------------------- | | `Function` | A free-standing or associated function. | | `Method` | A method defined inside a class, struct, trait, or impl block. | | `Class` | A class definition. | | `Struct` | A struct definition. | | `Interface` | An interface or protocol definition. | | `Enum` | An enum definition. | | `Module` | A module or package declaration. | | `Trait` | A trait definition. | | `Impl` | An impl block (Rust) or similar implementation block. | | `Namespace` | A namespace declaration. | | `Other` | A language-specific construct that does not fit any standard category. — Fields: `0`: `string` | *** #### CommentKind [Section titled “CommentKind”](#commentkind) The kind of a comment found in source code. Distinguishes between single-line comments, block (multi-line) comments, and documentation comments. | Value | Description | | ------- | --------------------------------------------------------------------- | | `Line` | A single-line comment (e.g., `// ...` or `# ...`). | | `Block` | A block or multi-line comment using slash-star delimiters. | | `Doc` | A documentation comment such as `/// ...` or slash-double-star block. | *** #### DocstringFormat [Section titled “DocstringFormat”](#docstringformat) The format of a docstring extracted from source code. Identifies the docstring convention used, which varies by language (e.g., Python triple-quoted strings, JSDoc, Rustdoc `///` comments). ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-2) Unit variants serialize as a bare string (`"JSDoc"`); the `Other` variant serializes as a single-keyed object (`{"Other": "rst"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ------------------- | -------------------------------------------------------------------------------------------------- | | `PythonTripleQuote` | Python triple-quoted string docstring (`"""..."""`). | | `JsDoc` | JavaScript/TypeScript JSDoc block comment (opens with two stars, closes with star-slash). | | `Rustdoc` | Rust `///` or `//!` doc comment. | | `GoDoc` | Go doc comment (a comment block immediately preceding a declaration). | | `JavaDoc` | Java Javadoc block comment (opens with two stars, closes with star-slash). | | `Other` | A language-specific docstring format not covered by the standard variants. — Fields: `0`: `string` | *** #### ExportKind [Section titled “ExportKind”](#exportkind) The kind of an export statement found in source code. Covers named exports, default exports, and re-exports from other modules. | Value | Description | | ---------- | -------------------------------------------------------------------- | | `Named` | A named export (e.g., `export { foo }`). | | `Default` | A default export (e.g., `export default foo`). | | `ReExport` | A re-export from another module (e.g., `export { foo } from 'bar'`). | *** #### SymbolKind [Section titled “SymbolKind”](#symbolkind) The kind of a symbol definition found in source code. Categorizes symbol definitions such as variables, constants, functions, classes, types, interfaces, enums, and modules. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-3) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | --------------------------------------------------------------------------- | | `Variable` | A variable binding. | | `Constant` | A constant (immutable binding). | | `Function` | A function definition. | | `Class` | A class definition. | | `Type` | A type alias or typedef. | | `Interface` | An interface definition. | | `Enum` | An enum definition. | | `Module` | A module declaration. | | `Other` | A symbol kind not covered by the standard variants. — Fields: `0`: `string` | *** #### DiagnosticSeverity [Section titled “DiagnosticSeverity”](#diagnosticseverity) Severity level of a diagnostic produced during parsing. Used to classify parse errors, warnings, and informational messages found in the syntax tree. | Value | Description | | --------- | --------------------------------------------------------------- | | `Error` | A parse error (e.g., an `ERROR` or `MISSING` node in the tree). | | `Warning` | A warning-level diagnostic. | | `Info` | An informational diagnostic. | *** ### Errors [Section titled “Errors”](#errors) #### Error [Section titled “Error”](#error) Errors that can occur when using the tree-sitter language pack. Covers language lookup failures, parse errors, query errors, and I/O issues. Feature-gated variants are included when `config`, `download`, or related features are enabled. ##### Matching on `Error` [Section titled “Matching on Error”](#matching-on-error) The set of variants is not stable: new failure modes are added in minor releases, and `Io`, `Json`, and `Toml` exist only under certain feature combinations, so the variant set a downstream crate sees depends on which features it enables. Downstream `match`es must therefore carry a `_` arm; `#[non_exhaustive]` makes the compiler enforce that instead of letting a feature change silently break a build. ##### C ABI error codes [Section titled “C ABI error codes”](#c-abi-error-codes) Each variant alef can see carries an explicit `alef(error_code = N)` allocation that becomes a member of the generated `AlefFfiErrorCode` C enum. These numbers are a public ABI contract: **an allocated number is never reused after its variant is removed**, and a variant’s number never changes, because C callers compare against the value, not the name. New variants take the next free number. 0-4 are reserved by alef, so allocation starts at 100. An unannotated variant is emitted as the unknown code rather than as itself, which silently flattens the taxonomy — annotate every new variant. | Variant | Description | | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `LanguageNotFound` | The requested language name (or alias) was not found in the registry. | | `DynamicLoad` | A dynamic shared library could not be loaded at runtime. | | `NullLanguagePointer` | The tree-sitter language function returned a null pointer for the given language name. | | `ParserSetup` | The language could not be applied to the parser (e.g., ABI version mismatch). | | `LockPoisoned` | An internal `RwLock` or `Mutex` was poisoned by a previous panic. | | `Config` | A configuration file or value was invalid or could not be applied. | | `ParseFailed` | The tree-sitter parser returned no tree for the given source input. | | `ParseTimeout` | The parse was cancelled because it exceeded its configured wall-clock budget. Raised only when a budget is configured — see `ProcessConfig::parse_timeout_ms`, which defaults to `null`. | | `QueryError` | A tree-sitter query could not be compiled or executed. | | `InvalidRange` | A byte range was invalid (e.g., end before start, or out of bounds). | | `Download` | A parser download from GitHub releases failed. | | `ChecksumMismatch` | The downloaded file’s SHA-256 digest did not match the manifest’s expected value. | | `CacheLock` | The cross-process download cache lock file could not be acquired or created. | *** # Python API Reference ## Python API Reference v1.16.1 [Section titled “Python API Reference v1.16.1”](#python-api-reference-v1161) ### Functions [Section titled “Functions”](#functions) #### detect\_language\_from\_extension() [Section titled “detect\_language\_from\_extension()”](#detect_language_from_extension) Detect language name from a file extension (without leading dot). Returns `None` for unrecognized extensions. The match is case-insensitive. **Signature:** ```python def detect_language_from_extension(ext: str) -> str | None ``` **Example:** ```python result = detect_language_from_extension("value") ``` **Parameters:** | Name | Type | Required | Description | | ----- | ----- | -------- | ----------- | | `ext` | `str` | Yes | The ext | **Returns:** `str | None` *** #### detect\_language\_from\_path() [Section titled “detect\_language\_from\_path()”](#detect_language_from_path) Detect language name from a file path. Extracts the file extension and looks it up. Returns `None` if the path has no extension or the extension is not recognized. **Signature:** ```python def detect_language_from_path(path: str) -> str | None ``` **Example:** ```python result = detect_language_from_path("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ----- | -------- | ---------------- | | `path` | `str` | Yes | Path to the file | **Returns:** `str | None` *** #### detect\_language\_from\_content() [Section titled “detect\_language\_from\_content()”](#detect_language_from_content) Detect language name from file content using the shebang line (`#!`). Inspects only the first line of `content`. If it begins with `#!`, the interpreter name is extracted and mapped to a language name. Handles common patterns: * `#!/usr/bin/env python3` → `"python"` * `#!/bin/bash` → `"bash"` * `#!/usr/bin/env node` → `"javascript"` The `-S` flag accepted by some `env` implementations is skipped automatically. Version suffixes (e.g. `python3.11`, `ruby3.2`) are stripped before matching. A leading UTF-8 BOM (`U+FEFF`) is skipped before the `#!` check, so a BOM-prefixed script is still detected by its shebang. Returns `None` when content does not start with `#!` (after stripping a leading BOM), the shebang is malformed, or the interpreter is not recognised. **Signature:** ```python def detect_language_from_content(content: str) -> str | None ``` **Example:** ```python result = detect_language_from_content("value") ``` **Parameters:** | Name | Type | Required | Description | | --------- | ----- | -------- | ---------------------- | | `content` | `str` | Yes | The content to process | **Returns:** `str | None` *** #### get\_highlights\_query() [Section titled “get\_highlights\_query()”](#get_highlights_query) Get the highlights query for a language, if bundled. Returns the contents of `highlights.scm` as a static string, or `None` if no highlights query is bundled for this language. **Signature:** ```python def get_highlights_query(language: str) -> str | None ``` **Example:** ```python result = get_highlights_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ----- | -------- | ------------ | | `language` | `str` | Yes | The language | **Returns:** `str | None` *** #### get\_injections\_query() [Section titled “get\_injections\_query()”](#get_injections_query) Get the injections query for a language, if bundled. Returns the contents of `injections.scm` as a static string, or `None` if no injections query is bundled for this language. **Signature:** ```python def get_injections_query(language: str) -> str | None ``` **Example:** ```python result = get_injections_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ----- | -------- | ------------ | | `language` | `str` | Yes | The language | **Returns:** `str | None` *** #### get\_locals\_query() [Section titled “get\_locals\_query()”](#get_locals_query) Get the locals query for a language, if bundled. Returns the contents of `locals.scm` as a static string, or `None` if no locals query is bundled for this language. **Signature:** ```python def get_locals_query(language: str) -> str | None ``` **Example:** ```python result = get_locals_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ----- | -------- | ------------ | | `language` | `str` | Yes | The language | **Returns:** `str | None` *** #### get\_tags\_query() [Section titled “get\_tags\_query()”](#get_tags_query) Get the tags query for a language, if bundled. Returns the contents of `tags.scm` as a static string, or `None` if no tags query is bundled for this language. **Signature:** ```python def get_tags_query(language: str) -> str | None ``` **Example:** ```python result = get_tags_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ----- | -------- | ------------ | | `language` | `str` | Yes | The language | **Returns:** `str | None` *** #### get\_indents\_query() [Section titled “get\_indents\_query()”](#get_indents_query) Get the indents query for a language, if bundled. Returns the contents of `indents.scm` (used for auto-indentation) as a static string, or `None` if no indents query is bundled for this language. **Signature:** ```python def get_indents_query(language: str) -> str | None ``` **Example:** ```python result = get_indents_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ----- | -------- | ------------ | | `language` | `str` | Yes | The language | **Returns:** `str | None` *** #### get\_folds\_query() [Section titled “get\_folds\_query()”](#get_folds_query) Get the folds query for a language, if bundled. Returns the contents of `folds.scm` (used for code folding) as a static string, or `None` if no folds query is bundled for this language. **Signature:** ```python def get_folds_query(language: str) -> str | None ``` **Example:** ```python result = get_folds_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ----- | -------- | ------------ | | `language` | `str` | Yes | The language | **Returns:** `str | None` *** #### get\_language() [Section titled “get\_language()”](#get_language) Get a tree-sitter `Language` by name using the global registry. Resolves language aliases (e.g., `"shell"` maps to `"bash"`). When the `download` feature is enabled (default), automatically downloads the parser from GitHub releases if not found locally. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.Download` if auto-download fails. **Signature:** ```python def get_language(name: str) -> Language ``` **Example:** ```python result = get_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ----- | -------- | ----------- | | `name` | `str` | Yes | The name | **Returns:** `Language` **Errors:** Raises `Error`. *** #### get\_parser() [Section titled “get\_parser()”](#get_parser) Get a `Parser` pre-configured for the given language. This is a convenience function that calls `get_language` and configures a new parser in one step. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language cannot be applied to the parser. **Signature:** ```python def get_parser(name: str) -> Parser ``` **Example:** ```python result = get_parser("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ----- | -------- | ----------- | | `name` | `str` | Yes | The name | **Returns:** `Parser` **Errors:** Raises `Error`. *** #### detect\_language() [Section titled “detect\_language()”](#detect_language) Detect language name from a file path or extension. This compatibility alias matches the pre-Alef Python binding API. **Signature:** ```python def detect_language(path: str) -> str | None ``` **Example:** ```python result = detect_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ----- | -------- | ---------------- | | `path` | `str` | Yes | Path to the file | **Returns:** `str | None` *** #### available\_languages() [Section titled “available\_languages()”](#available_languages) List all available language names (sorted, deduplicated, includes aliases). Returns names of both statically compiled and dynamically loadable languages, plus any configured aliases. **Signature:** ```python def available_languages() -> list[str] ``` **Example:** ```python result = available_languages() ``` **Returns:** `list[str]` *** #### has\_language() [Section titled “has\_language()”](#has_language) Check if a language is available by name or alias. Returns `True` if the language can be loaded (statically compiled, dynamically available, or a known alias for one of these). **Signature:** ```python def has_language(name: str) -> bool ``` **Example:** ```python result = has_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ----- | -------- | ----------- | | `name` | `str` | Yes | The name | **Returns:** `bool` *** #### language\_count() [Section titled “language\_count()”](#language_count) Return the number of available languages. Includes statically compiled languages, dynamically loadable languages, and aliases. **Signature:** ```python def language_count() -> int ``` **Example:** ```python result = language_count() ``` **Returns:** `int` *** #### process() [Section titled “process()”](#process) Process source code and extract file intelligence using the global registry. Parses the source with tree-sitter and extracts metrics, structure, imports, exports, comments, docstrings, symbols, diagnostics, and/or chunks based on the flags set in `ProcessConfig`. **Errors:** Returns `Error.InvalidRange` if the config carries a zero-valued limit or the source exceeds `ProcessConfig.max_source_bytes`, `Error.ParseTimeout` if the parse exceeds `ProcessConfig.parse_timeout_ms`, `Error.LanguageNotFound` if the language is unknown, or `Error.ParseFailed` if parsing yields no tree. **Signature:** ```python def process(source: str, config: ProcessConfig) -> ProcessResult ``` **Example:** ```python result = process("value", ProcessConfig()) ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `str` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Raises `Error`. *** #### init() [Section titled “init()”](#init) Initialize the language pack with the given configuration. Applies any custom cache directory, then downloads all languages and groups specified in the config. This is the recommended entry point when you want to pre-warm the cache before use. **Errors:** Returns an error if configuration cannot be applied or if downloads fail. **Signature:** ```python def init(config: PackConfig) -> None ``` **Example:** ```python init(PackConfig()) ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Raises `Error`. *** #### configure() [Section titled “configure()”](#configure) Apply download configuration without downloading anything. Use this to set a custom cache directory before the first call to `get_language` or any download function. Changing the cache dir after languages have been registered has no effect on already-loaded languages. `PackConfig.cache_dir` is a BASE directory, not the final libs path: this crate appends `tree-sitter-language-pack/v{version}/libs` to it, the same suffix applied to the platform default cache directory. In the example below, files actually land under `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`, never directly in `/tmp/my-parsers/`. Call `cache_dir` to read back the resolved, fully-suffixed path. **Errors:** Returns an error if the lock cannot be acquired. **Signature:** ```python def configure(config: PackConfig) -> None ``` **Example:** ```python configure(PackConfig()) ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Raises `Error`. *** #### download() [Section titled “download()”](#download) Download specific languages to the local cache. Returns the number of distinct languages available after the call. Already compiled or cached languages are included in the count. Aliases are resolved before counting, so `["shell", "bash"]` names one language and returns 1. **Errors:** Returns an error if any language is not available in the manifest or if the download fails. **Signature:** ```python def download(names: list[str]) -> int ``` **Example:** ```python result = download([]) ``` **Parameters:** | Name | Type | Required | Description | | ------- | ------------- | -------- | ----------- | | `names` | `list\[str\]` | Yes | The names | **Returns:** `int` **Errors:** Raises `Error`. *** #### prefetch() [Section titled “prefetch()”](#prefetch) Prefetch grammars: download any not already loadable from disk, then load every requested language into the process registry so a subsequent hot loop only parses. Unlike `download()`, this does not trust in-memory availability — it downloads whenever a grammar is not actually loadable from disk (fixing the case where a known-but-not-downloaded grammar is reported present), then resolves and caches every requested language. Call it once, up front, before a parallel workload. **Errors:** Returns `Error.Download` if a required grammar cannot be fetched, or `Error.LanguageNotFound` if a requested name is unknown. **Signature:** ```python def prefetch(languages: list[str]) -> None ``` **Example:** ```python prefetch([]) ``` **Parameters:** | Name | Type | Required | Description | | ----------- | ------------- | -------- | ------------- | | `languages` | `list\[str\]` | Yes | The languages | **Returns:** No return value. **Errors:** Raises `Error`. *** #### download\_all() [Section titled “download\_all()”](#download_all) Download all available languages from the remote manifest. Downloads the platform bundle and extracts every library it contains. Languages that appear in the manifest but are absent from the bundle (e.g. grammars that failed to compile at release time) are silently skipped — they are not treated as an error. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns an error if the manifest cannot be fetched or the bundle download fails. **Signature:** ```python def download_all() -> int ``` **Example:** ```python result = download_all() ``` **Returns:** `int` **Errors:** Raises `Error`. *** #### download\_group() [Section titled “download\_group()”](#download_group) Download every language in a named group. Groups are defined by the remote manifest, not by this library, and let you ensure a curated set of related grammars in one call instead of listing each name to `download()`. Already-cached languages are skipped. Call `manifest_groups` to discover the group names the manifest actually defines. The published manifest currently defines a single group, `"all"`; earlier revisions of this documentation advertised `"web"`, `"data"`, and `"systems"`, which the manifest has never contained, so every call following that example failed. Do not hardcode a group name without checking. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns `Error.Download` if the manifest cannot be fetched, if the group is unknown — the message lists the groups the manifest defines — or if any constituent language fails to download. **Signature:** ```python def download_group(name: str) -> int ``` **Example:** ```python result = download_group("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ----- | -------- | ----------- | | `name` | `str` | Yes | The name | **Returns:** `int` **Errors:** Raises `Error`. *** #### manifest\_languages() [Section titled “manifest\_languages()”](#manifest_languages) Return all language names available in the remote manifest (371). Fetches (and caches) the remote manifest to discover the full list of downloadable languages. Use `downloaded_languages` to list what is already cached locally. **Errors:** Returns an error if the manifest cannot be fetched. **Signature:** ```python def manifest_languages() -> list[str] ``` **Example:** ```python result = manifest_languages() ``` **Returns:** `list[str]` **Errors:** Raises `Error`. *** #### manifest\_groups() [Section titled “manifest\_groups()”](#manifest_groups) Return the names of every language group the remote manifest defines, sorted. Group names are manifest data, not a compile-time constant of this library, so this is the only reliable way to learn what `download_group` and `PackConfig.groups` accept. The published manifest currently defines just `"all"`. **Errors:** Returns `Error.Download` if the manifest cannot be fetched. **Signature:** ```python def manifest_groups() -> list[str] ``` **Example:** ```python result = manifest_groups() ``` **Returns:** `list[str]` **Errors:** Raises `Error`. *** #### downloaded\_languages() [Section titled “downloaded\_languages()”](#downloaded_languages) Return languages that are already downloaded and cached locally. Does not perform any network requests. Returns an empty list if the cache directory does not exist or cannot be read. **Signature:** ```python def downloaded_languages() -> list[str] ``` **Example:** ```python result = downloaded_languages() ``` **Returns:** `list[str]` *** #### clean\_cache() [Section titled “clean\_cache()”](#clean_cache) Delete all cached parser shared libraries. Resets the cache registration so the next call to `get_language` or a download function will re-register the (now empty) cache directory. **Errors:** Returns an error if the cache directory cannot be removed. **Signature:** ```python def clean_cache() -> None ``` **Example:** ```python clean_cache() ``` **Returns:** No return value. **Errors:** Raises `Error`. *** #### cache\_dir() [Section titled “cache\_dir()”](#cache_dir) Return the effective cache directory path. This is `{base}/tree-sitter-language-pack/v{version}/libs/`, where `{base}` is either the custom BASE directory set via `configure` / `init` (`PackConfig.cache_dir`) or the platform default cache directory — both are suffixed identically, so a custom `cache_dir` is never used as the final libs path. The default resolves to `~/.cache/tree-sitter-language-pack/v{version}/libs/` on a typical Unix system. **Errors:** Returns an error if no cache directory can be resolved: `version` is somehow invalid, or (with no custom `cache_dir` configured) the platform reports none and `TREE_SITTER_LANGUAGE_PACK_CACHE_DIR` is unset. This crate no longer falls back to the temporary directory for the latter case — see #101 H2. **Signature:** ```python def cache_dir() -> str ``` **Example:** ```python result = cache_dir() ``` **Returns:** `str` **Errors:** Raises `Error`. *** ### Types [Section titled “Types”](#types) #### ByteRange [Section titled “ByteRange”](#byterange) A byte range — start (inclusive) to end (exclusive). | Field | Type | Default | Description | | ------- | ----- | ------- | ---------------------------- | | `start` | `int` | — | Inclusive start byte offset. | | `end` | `int` | — | Exclusive end byte offset. | *** #### ChunkContext [Section titled “ChunkContext”](#chunkcontext) Metadata for a single chunk of source code. | Field | Type | Default | Description | | ----------------- | ----------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `str` | — | Language name used to parse this chunk. | | `chunk_index` | `int` | — | Zero-indexed position of this chunk within the file’s chunk list. | | `total_chunks` | `int` | — | Total number of chunks the file was split into. | | `node_types` | `list\[str\]` | `[]` | Tree-sitter node kinds that appear at the top level of this chunk. | | `context_path` | `list\[str\]` | `[]` | Hierarchical path of enclosing structural items (e.g., `["MyClass", "my_method"]`). | | `symbols_defined` | `list\[str\]` | `[]` | Names of symbols defined within this chunk. | | `comments` | `list\[CommentInfo\]` | `[]` | Comments contained within this chunk. | | `docstrings` | `list\[DocstringInfo\]` | `[]` | Docstrings contained within this chunk. Populated only for Python — the same language for which `ProcessResult.docstrings` is populated, and by the same classifier. Always empty for every other language. | | `has_error_nodes` | `bool` | — | Whether this chunk contains any tree-sitter error nodes. | *** #### CodeChunk [Section titled “CodeChunk”](#codechunk) A chunk of source code with rich metadata. | Field | Type | Default | Description | | ------------ | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `content` | `str` | — | The raw source text of this chunk. | | `start_byte` | `int` | — | Inclusive start byte offset of this chunk in the original source. | | `end_byte` | `int` | — | Exclusive end byte offset of this chunk in the original source. | | `start_line` | `int` | — | Zero-indexed start line of this chunk. | | `end_line` | `int` | — | Zero-indexed row of the last byte actually included in this chunk (inclusive — the same row a `Span.end_line` would report for a node ending on that byte). Computed the same way regardless of whether the source has a trailing newline: it is always the row of `end_byte - 1`, never a phantom row past the file’s real content. | | `metadata` | `ChunkContext` | — | Contextual metadata about this chunk. | *** #### CommentInfo [Section titled “CommentInfo”](#commentinfo) A comment extracted from source code. | Field | Type | Default | Description | | ----------------- | ------------- | ------------------ | ----------------------------------------------------------------- | | `text` | `str` | — | The raw text content of the comment. | | `kind` | `CommentKind` | `CommentKind.LINE` | The kind of comment (line, block, or doc). | | `span` | `Span` | — | Source span covering the comment. | | `associated_node` | `str \| None` | `None` | Name of the syntax node this comment is directly associated with. | *** #### DataAttribute [Section titled “DataAttribute”](#dataattribute) An XML-style attribute attached to an `Element` node. Populated only for `DataNodeKind.Element`; always empty for `KeyValue` and `Sequence` nodes. | Field | Type | Default | Description | | ------- | ------ | ------- | --------------------------------------------------------------- | | `name` | `str` | — | Attribute name (e.g. `"class"`, `"href"`). | | `value` | `str` | — | Attribute value as a raw string (quotes stripped). | | `span` | `Span` | — | Source span covering the entire `name="value"` attribute token. | *** #### DataNode [Section titled “DataNode”](#datanode) A node in the hierarchical data tree produced by data-format extraction. When `ProcessConfig.data_extraction` is `True`, `ProcessResult.data` is populated with a root `DataNode` whose `children` mirror the structure of the parsed file. The `kind` field determines which other fields are meaningful: | `kind` | `key` | `value` | `attributes` | `children` | | ---------- | ------------------------- | ------------ | ------------ | -------------- | | `KeyValue` | key / mapping key / index | leaf value | empty | nested map | | `Element` | XML tag name | text content | XML attrs | child elements | | `Sequence` | positional index (`"0"`) | leaf value | empty | sub-items | | Field | Type | Default | Description | | ------------ | ----------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------- | | `kind` | `DataNodeKind` | `DataNodeKind.KEY_VALUE` | Whether this node is a key/value pair, XML element, or sequence item. | | `key` | `str \| None` | `None` | Key, attribute name, tag name, or positional index (`"0"`, `"1"`, …). `None` at the document root. | | `value` | `str \| None` | `None` | Leaf scalar value, if any. `None` for containers (objects, arrays, XML elements with child elements). | | `attributes` | `list\[DataAttribute\]` | `[]` | Attributes on element-shape nodes (XML `STag` attributes). Empty for all other kinds. | | `children` | `list\[DataNode\]` | `[]` | Children for nested containers and XML element bodies. | | `span` | `Span` | — | Source span covering this node in the original source file. | *** #### Diagnostic [Section titled “Diagnostic”](#diagnostic) A diagnostic (syntax error, missing node, etc.) from parsing. | Field | Type | Default | Description | | ---------- | -------------------- | -------------------------- | ---------------------------------------------- | | `message` | `str` | — | Human-readable description of the diagnostic. | | `severity` | `DiagnosticSeverity` | `DiagnosticSeverity.ERROR` | Severity of the diagnostic. | | `span` | `Span` | — | Source span where the diagnostic was detected. | *** #### DocSection [Section titled “DocSection”](#docsection) A section within a docstring (e.g., Args, Returns, Raises). | Field | Type | Default | Description | | ------------- | ------------- | ------- | ------------------------------------------------------- | | `kind` | `str` | — | Section kind (e.g., `"args"`, `"returns"`, `"raises"`). | | `name` | `str \| None` | `None` | Parameter or return value name, if applicable. | | `description` | `str` | — | Description text for this section. | *** #### DocstringInfo [Section titled “DocstringInfo”](#docstringinfo) A docstring extracted from source code. | Field | Type | Default | Description | | ----------------- | -------------------- | ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | `str` | — | The raw text of the docstring. | | `format` | `DocstringFormat` | `DocstringFormat.PYTHON_TRIPLE_QUOTE` | The docstring format (Python, JSDoc, Rustdoc, etc.). | | `span` | `Span` | — | Source span covering the docstring. | | `associated_item` | `str \| None` | `None` | Name of the item this docstring documents. | | `parsed_sections` | `list\[DocSection\]` | `[]` | Parsed sections of the docstring (Args, Returns, Raises, etc.). **Reserved: not yet populated.** Always empty, for every `DocstringFormat`. Parsing a docstring body into sections requires implementing each convention’s own layout (Google/NumPy/reST style for Python, `@param`/`@returns` for JSDoc/Javadoc, and so on), which no extractor here does yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | *** #### DownloadManager [Section titled “DownloadManager”](#downloadmanager) Manages downloading and caching of pre-built parser shared libraries. ##### Methods [Section titled “Methods”](#methods) ###### new() [Section titled “new()”](#new) Create a new download manager for the given version. **Errors:** Returns `Error.Download` if `version` is empty, contains a path separator or `..`, or contains a character outside `[A-Za-z0-9.+-]` — see `validate_version` — or if no cache directory can be resolved (see `Self.default_cache_dir`). **Signature:** ```python @staticmethod def new(version: str) -> DownloadManager ``` **Example:** ```python result = DownloadManager.new("value") ``` **Parameters:** | Name | Type | Required | Description | | --------- | ----- | -------- | ----------- | | `version` | `str` | Yes | The version | **Returns:** `DownloadManager` **Errors:** Raises `Error`. ###### installed\_languages() [Section titled “installed\_languages()”](#installed_languages) List languages that are already downloaded and cached. Derived from the on-disk cache filenames, one canonical name per file, plus every alias that resolves to it (via `aliases_for`) — so this list agrees with the user-facing `LanguageRegistry.available_languages` about which names are “available”; both report `"shell"` once `bash` is cached, for example. A previous version reported canonical names only, which could never agree with `available_languages()`. See #107. Returns an empty list if the cache directory does not exist. If it exists but cannot be read (e.g. a permission error), also returns an empty list — changing this to a `Result` would be a breaking change across every language binding — but logs a `tracing.warn!` so the failure is not silently indistinguishable from “nothing installed”. **Signature:** ```python def installed_languages(self) -> list[str] ``` **Example:** ```python result = instance.installed_languages() ``` **Returns:** `list[str]` ###### download\_all\_best\_effort() [Section titled “download\_all\_best\_effort()”](#download_all_best_effort) Download the platform bundle and extract every library file it contains. Unlike `Self.ensure_languages`, this does not check the manifest language list against archive contents — it simply extracts all `.so`/`.dylib`/`.dll` files from the bundle. Languages in the manifest that are missing from the archive are silently ignored rather than returning an error. Returns the number of library files extracted (including those already cached). **Signature:** ```python def download_all_best_effort(self) -> int ``` **Example:** ```python result = instance.download_all_best_effort() ``` **Returns:** `int` **Errors:** Raises `Error`. ###### clean\_cache() [Section titled “clean\_cache()”](#clean_cache-1) Remove all cached parser libraries. Acquires the cross-process lock so `clean_cache` cannot race a concurrent downloader (avoids Windows sharing-violation errors against an in-flight bundle write). The `.download.lock` file itself is **not** removed — it is permanent infrastructure; deleting it could allow a concurrent process that already opened the file to continue holding a stale lock handle while a new process opens a fresh inode, breaking the mutual-exclusion guarantee. **Signature:** ```python def clean_cache(self) -> None ``` **Example:** ```python instance.clean_cache() ``` **Returns:** No return value. **Errors:** Raises `Error`. *** #### ExportInfo [Section titled “ExportInfo”](#exportinfo) An export statement extracted from source code. | Field | Type | Default | Description | | ------ | ------------ | ------------------ | -------------------------------------------------- | | `name` | `str` | — | The exported name. | | `kind` | `ExportKind` | `ExportKind.NAMED` | The kind of export (named, default, or re-export). | | `span` | `Span` | — | Source span covering the export statement. | *** #### FileMetrics [Section titled “FileMetrics”](#filemetrics) Aggregate metrics for a source file. | Field | Type | Default | Description | | --------------- | ----- | ------- | -------------------------------------------------------------- | | `total_lines` | `int` | — | Total number of lines (including blank and comment lines). | | `code_lines` | `int` | — | Number of lines containing non-blank, non-comment source code. | | `comment_lines` | `int` | — | Number of lines that are entirely comments. | | `blank_lines` | `int` | — | Number of blank (whitespace-only) lines. | | `total_bytes` | `int` | — | Total byte length of the source file. | | `node_count` | `int` | — | Total number of nodes in the syntax tree. | | `error_count` | `int` | — | Number of error nodes in the syntax tree (parse errors). | | `max_depth` | `int` | — | Maximum nesting depth reached in the syntax tree. | *** #### ImportInfo [Section titled “ImportInfo”](#importinfo) An import statement extracted from source code. | Field | Type | Default | Description | | ------------- | ------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `source` | `str` | — | The module or path being imported from. | | `items` | `list\[str\]` | `[]` | Specific names imported from the source module. For `import a, b` / `from m import a, b`, every entry’s base name (never the alias). For a JavaScript/TypeScript named-imports clause (`import { a, b as c } from 'm'`), every specifier’s original name. Populated for Python and JavaScript/TypeScript only. Always empty for every other language this library recognises import statements for — Rust, Go, Java, Kotlin, and Elixir (`import`/`alias`/`require`/`use`) — and for a JS/TS namespace import (`import * as ns`) or default import (`import x from 'm'`), neither of which names individual items. | | `alias` | `str \| None` | `None` | Alias assigned to the import (e.g., `import numpy as np`). Populated for Python’s single-name form (`import numpy as np`, `from m import a as b`) and JavaScript/TypeScript’s namespace form (`import * as ns from 'm'`) or a named-imports clause naming exactly one specifier (`import { a as b } from 'm'`). `None` for Rust, Go, Java, Kotlin, and Elixir (which has its own `as:` alias option on `alias` directives, not yet extracted here) — and for a Python statement that aliases several names at once (`import os, sys as s`), where there is no single alias to report for the statement as a whole, so only `items` is populated for it. | | `is_wildcard` | `bool` | — | Whether this is a wildcard import (e.g., `import *` or `use foo.*`). Detected from the syntax tree — a dedicated wildcard node (`wildcard_import` in Python, `use_wildcard` in Rust) or a bare `*` token outside of string-literal content — not by searching the import’s source text for a `*` character, so a glob in an import path string (`import a from './glob*.js'`) is not mistaken for one. | | `span` | `Span` | — | Source span covering the import statement. | *** #### Language [Section titled “Language”](#language) *** #### LanguageRegistry [Section titled “LanguageRegistry”](#languageregistry) Thread-safe registry of tree-sitter language parsers. Manages both statically compiled and dynamically loaded language grammars. Use `LanguageRegistry.new()` for the default registry, or access the global instance via the module-level convenience functions (`get_language`, `available_languages`, etc.). ##### Methods [Section titled “Methods”](#methods-1) ###### new() [Section titled “new()”](#new-1) Create a new registry populated with all statically compiled languages. When the `dynamic-loading` feature is enabled, the registry also knows about dynamically loadable grammars and will load them on demand. **Signature:** ```python @staticmethod def new() -> LanguageRegistry ``` **Example:** ```python result = LanguageRegistry.new() ``` **Returns:** `LanguageRegistry` ###### get\_language() [Section titled “get\_language()”](#get_language-1) Get a tree-sitter `Language` by name. Resolves aliases (e.g., `"shell"` -> `"bash"`, `"makefile"` -> `"make"`), then looks up the language in the static table. When the `dynamic-loading` feature is enabled, falls back to loading a shared library on demand. **Errors:** Returns `Error.LanguageNotFound` if the name (after alias resolution) does not match any known grammar. **Signature:** ```python def get_language(self, name: str) -> Language ``` **Example:** ```python result = instance.get_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ----- | -------- | ----------- | | `name` | `str` | Yes | The name | **Returns:** `Language` **Errors:** Raises `Error`. ###### available\_languages() [Section titled “available\_languages()”](#available_languages-1) List all available language names, sorted and deduplicated. Includes statically compiled languages, dynamically loadable languages (if the `dynamic-loading` feature is enabled), and all configured aliases. **Signature:** ```python def available_languages(self) -> list[str] ``` **Example:** ```python result = instance.available_languages() ``` **Returns:** `list[str]` ###### has\_parser() [Section titled “has\_parser()”](#has_parser) Check whether this language can be parsed right now, without downloading. Resolves aliases, then answers from exactly the lookup `get_language` performs: the statically compiled table, the already-loaded dynamic grammars, and the parser shared libraries present in the primary and extra (download-cache) library directories. It never performs network I/O. A previous implementation consulted only the statically compiled table. That table is empty in every build that does not set `TSLP_LANGUAGES`, so the function answered `False` for languages this registry parses perfectly well. Contrast `has_language`, which is also `True` for a grammar that is merely *known to the manifest* and would have to be downloaded first. The pair distinguishes “we can parse it offline, now” from “we recognise the name”. The first `True` answer for a dynamic grammar loads its shared library: loading is the only way to know the grammar is usable, since a truncated or wrong-architecture library exists on disk but cannot parse. Loads are cached process-wide, so repeat calls are cheap. **Signature:** ```python def has_parser(self, name: str) -> bool ``` **Example:** ```python result = instance.has_parser("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ----- | -------- | ----------- | | `name` | `str` | Yes | The name | **Returns:** `bool` ###### has\_language() [Section titled “has\_language()”](#has_language-1) Check whether a language is available by name or alias. Returns `True` if the language can be loaded, either from the static table or from a dynamic library on disk. Every branch is one more way to answer `True`, so they are ordered cheapest-first and the filesystem is only consulted once every in-memory source has said no. Probing the loaded-grammar map and the manifest ahead of the `stat` calls is what keeps this off the syscall path for the languages a process actually uses. **Signature:** ```python def has_language(self, name: str) -> bool ``` **Example:** ```python result = instance.has_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ----- | -------- | ----------- | | `name` | `str` | Yes | The name | **Returns:** `bool` ###### language\_count() [Section titled “language\_count()”](#language_count-1) Return the total number of available languages (including aliases). Counts the same set `available_languages` lists, without materialising or sorting it. **Signature:** ```python def language_count(self) -> int ``` **Example:** ```python result = instance.language_count() ``` **Returns:** `int` ###### process() [Section titled “process()”](#process-1) Parse source code and extract file intelligence based on config in a single pass. **Errors:** Returns `Error.InvalidRange` if the config is invalid (see `ProcessConfig.validate`) or if the source exceeds the configured `max_source_bytes`; `Error.LanguageNotFound` if the language is unknown; or `Error.ParseFailed` if parsing produces no tree. **Signature:** ```python def process(self, source: str, config: ProcessConfig) -> ProcessResult ``` **Example:** ```python result = instance.process("value", ProcessConfig()) ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `str` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Raises `Error`. *** #### Node [Section titled “Node”](#node) A single syntax node within a `Tree`. Nodes hold a strong reference to their parent tree so they remain valid regardless of how the tree is moved or stored at the FFI boundary. ##### Methods [Section titled “Methods”](#methods-2) ###### kind() [Section titled “kind()”](#kind) Return the node’s kind name (e.g. `"function_definition"`). **Signature:** ```python def kind(self) -> str ``` **Example:** ```python result = instance.kind() ``` **Returns:** `str` ###### kind\_id() [Section titled “kind\_id()”](#kind_id) Return the node’s numeric kind ID. Tree-sitter assigns a stable `u16` ID to every node kind in a grammar (e.g. `"function_definition" → 42`). Comparing `kind_id()` is cheaper than comparing the string `kind()` in tight AST loops. **Signature:** ```python def kind_id(self) -> int ``` **Example:** ```python result = instance.kind_id() ``` **Returns:** `int` ###### start\_byte() [Section titled “start\_byte()”](#start_byte) Return the inclusive start byte offset of this node. **Signature:** ```python def start_byte(self) -> int ``` **Example:** ```python result = instance.start_byte() ``` **Returns:** `int` ###### end\_byte() [Section titled “end\_byte()”](#end_byte) Return the exclusive end byte offset of this node. **Signature:** ```python def end_byte(self) -> int ``` **Example:** ```python result = instance.end_byte() ``` **Returns:** `int` ###### byte\_range() [Section titled “byte\_range()”](#byte_range) Return the node’s byte range as a `ByteRange`. Callers should slice their own source bytes — this is a zero-copy text accessor. **Signature:** ```python def byte_range(self) -> ByteRange ``` **Example:** ```python result = instance.byte_range() ``` **Returns:** `ByteRange` ###### start\_position() [Section titled “start\_position()”](#start_position) Return the start `Point` (row, column). **Signature:** ```python def start_position(self) -> Point ``` **Example:** ```python result = instance.start_position() ``` **Returns:** `Point` ###### end\_position() [Section titled “end\_position()”](#end_position) Return the end `Point` (row, column). **Signature:** ```python def end_position(self) -> Point ``` **Example:** ```python result = instance.end_position() ``` **Returns:** `Point` ###### is\_named() [Section titled “is\_named()”](#is_named) True when this node is named (not punctuation/whitespace). **Signature:** ```python def is_named(self) -> bool ``` **Example:** ```python result = instance.is_named() ``` **Returns:** `bool` ###### is\_error() [Section titled “is\_error()”](#is_error) True when this is an error node. **Signature:** ```python def is_error(self) -> bool ``` **Example:** ```python result = instance.is_error() ``` **Returns:** `bool` ###### is\_missing() [Section titled “is\_missing()”](#is_missing) True when this is a missing-token node. **Signature:** ```python def is_missing(self) -> bool ``` **Example:** ```python result = instance.is_missing() ``` **Returns:** `bool` ###### is\_extra() [Section titled “is\_extra()”](#is_extra) True when this is an “extra” node (e.g. a comment). **Signature:** ```python def is_extra(self) -> bool ``` **Example:** ```python result = instance.is_extra() ``` **Returns:** `bool` ###### has\_error() [Section titled “has\_error()”](#has_error) True when this node or any descendant is an error. **Signature:** ```python def has_error(self) -> bool ``` **Example:** ```python result = instance.has_error() ``` **Returns:** `bool` ###### parent() [Section titled “parent()”](#parent) Return this node’s parent, if any. **Signature:** ```python def parent(self) -> Node | None ``` **Example:** ```python result = instance.parent() ``` **Returns:** `Node | None` ###### child() [Section titled “child()”](#child) Return the i-th child of this node, if any. **Signature:** ```python def child(self, index: int) -> Node | None ``` **Example:** ```python result = instance.child(42) ``` **Parameters:** | Name | Type | Required | Description | | ------- | ----- | -------- | ----------- | | `index` | `int` | Yes | The index | **Returns:** `Node | None` ###### child\_count() [Section titled “child\_count()”](#child_count) Total number of children (including unnamed). **Signature:** ```python def child_count(self) -> int ``` **Example:** ```python result = instance.child_count() ``` **Returns:** `int` ###### named\_child() [Section titled “named\_child()”](#named_child) Return the i-th named child of this node, if any. **Signature:** ```python def named_child(self, index: int) -> Node | None ``` **Example:** ```python result = instance.named_child(42) ``` **Parameters:** | Name | Type | Required | Description | | ------- | ----- | -------- | ----------- | | `index` | `int` | Yes | The index | **Returns:** `Node | None` ###### named\_child\_count() [Section titled “named\_child\_count()”](#named_child_count) Number of named children of this node. **Signature:** ```python def named_child_count(self) -> int ``` **Example:** ```python result = instance.named_child_count() ``` **Returns:** `int` ###### child\_by\_field\_name() [Section titled “child\_by\_field\_name()”](#child_by_field_name) Look up a child by its grammar-defined field name. **Signature:** ```python def child_by_field_name(self, name: str) -> Node | None ``` **Example:** ```python result = instance.child_by_field_name("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ----- | -------- | ----------- | | `name` | `str` | Yes | The name | **Returns:** `Node | None` ###### to\_sexp() [Section titled “to\_sexp()”](#to_sexp) Return the S-expression form of this node’s subtree. **Signature:** ```python def to_sexp(self) -> str ``` **Example:** ```python result = instance.to_sexp() ``` **Returns:** `str` ###### walk() [Section titled “walk()”](#walk) Return a `TreeCursor` positioned at this node. **Signature:** ```python def walk(self) -> TreeCursor ``` **Example:** ```python result = instance.walk() ``` **Returns:** `TreeCursor` *** #### PackConfig [Section titled “PackConfig”](#packconfig) Configuration for the tree-sitter language pack. Controls cache directory and which languages to pre-download. Can be loaded from a TOML file, constructed programmatically, or passed as a dict/object from language bindings. | Field | Type | Default | Description | | ----------- | --------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cache_dir` | `str \| None` | `None` | Override the BASE directory the parser cache lives under. This is a base, not the final library path: the crate appends `tree-sitter-language-pack/v{version}/libs` to it, exactly as it does to the platform default. So `cache_dir = "/tmp/my-parsers"` resolves to `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`. The suffix is not cosmetic. It keeps the whole cache tree — manifest, bundles and lock file included — inside a directory this library owns and versions. Earlier releases used this path verbatim, which put those files in the configured directory’s PARENT and let a cache built by one crate version be reused by another. Default base: the platform cache dir, e.g. `~/.cache` on Linux. | | `languages` | `list\[str\] \| None` | `[]` | Languages to pre-download on init. Each entry is a language name (e.g. `"python"`, `"rust"`). | | `groups` | `list\[str\] \| None` | `[]` | Language groups to pre-download. Group names come from the remote manifest, so the valid set is not fixed by this library; the published manifest currently defines only `"all"`. Call `manifest_groups` to enumerate them. An unknown name makes `init` fail. | *** #### Parser [Section titled “Parser”](#parser) A tree-sitter parser configured for one language at a time. ##### Methods [Section titled “Methods”](#methods-3) ###### new() [Section titled “new()”](#new-2) Construct a new parser with no language set and no parse limits. Call `Parser.set_language` before parsing. Limits are opt-in via `set_max_source_bytes` and `set_parse_timeout_ms`; both default to unbounded so that existing callers are unaffected. **Signature:** ```python @staticmethod def new() -> Parser ``` **Example:** ```python result = Parser.new() ``` **Returns:** `Parser` ###### set\_max\_source\_bytes() [Section titled “set\_max\_source\_bytes()”](#set_max_source_bytes) Refuse to parse sources longer than `max_bytes`. `None` (the default) means no limit. Over-limit input makes `parse` and `parse_bytes` return `None` after emitting a `WARN`; input is never silently truncated. See `RECOMMENDED_MAX_SOURCE_BYTES`. **Signature:** ```python def set_max_source_bytes(self, max_bytes: int) -> None ``` **Example:** ```python instance.set_max_source_bytes(max_bytes=42) ``` **Parameters:** | Name | Type | Required | Description | | ----------- | ------------- | -------- | ------------- | | `max_bytes` | `int \| None` | No | The max bytes | **Returns:** No return value. ###### set\_parse\_timeout\_ms() [Section titled “set\_parse\_timeout\_ms()”](#set_parse_timeout_ms) Cancel a parse that exceeds `timeout_ms` milliseconds of wall clock. `None` (the default) means no budget. Cancellation runs through tree-sitter’s parse progress callback, so it is granular to that callback’s interval rather than exact. See `RECOMMENDED_PARSE_TIMEOUT_MS`. **Signature:** ```python def set_parse_timeout_ms(self, timeout_ms: int) -> None ``` **Example:** ```python instance.set_parse_timeout_ms(timeout_ms=42) ``` **Parameters:** | Name | Type | Required | Description | | ------------ | ------------- | -------- | -------------- | | `timeout_ms` | `int \| None` | No | The timeout ms | **Returns:** No return value. ###### set\_language() [Section titled “set\_language()”](#set_language) Configure the parser to use the language identified by name (e.g. `"python"`). Resolves the language through the global registry — auto-downloading if necessary, when the `download` feature is enabled. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language ABI is incompatible. **Signature:** ```python def set_language(self, name: str) -> None ``` **Example:** ```python instance.set_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | ----- | -------- | ----------- | | `name` | `str` | Yes | The name | **Returns:** No return value. **Errors:** Raises `Error`. ###### parse() [Section titled “parse()”](#parse) Parse a UTF-8 source string. Returns `None` if no language is set, if the parse was cancelled by the configured timeout, or if the source exceeds the configured size limit. Each non-parse outcome is logged, so an empty result is never silent. ###### Concurrency [Section titled “Concurrency”](#concurrency) Parsing runs fully in parallel across threads for almost every language — no lock is taken. The exception is the small set of grammars whose external scanner keeps mutable process-global state (currently just `properties`): parses of that language are serialized against each other through an internal per-language lock, so that concurrent threads can’t corrupt shared scanner state. Every other language is unaffected by that lock and never waits on it. **Signature:** ```python def parse(self, source: str) -> Tree | None ``` **Example:** ```python result = instance.parse("value") ``` **Parameters:** | Name | Type | Required | Description | | -------- | ----- | -------- | ----------- | | `source` | `str` | Yes | The source | **Returns:** `Tree | None` ###### parse\_bytes() [Section titled “parse\_bytes()”](#parse_bytes) Parse a raw byte slice. Same outcomes as `parse`, including the concurrency behaviour documented there. **Signature:** ```python def parse_bytes(self, source: bytes) -> Tree | None ``` **Example:** ```python result = instance.parse_bytes(b"data") ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------- | -------- | ----------- | | `source` | `bytes` | Yes | The source | **Returns:** `Tree | None` ###### reset() [Section titled “reset()”](#reset) Reset internal state. The next call to `parse` will not be incremental. **Signature:** ```python def reset(self) -> None ``` **Example:** ```python instance.reset() ``` **Returns:** No return value. *** #### Point [Section titled “Point”](#point) A source position — row + column, zero-indexed. | Field | Type | Default | Description | | -------- | ----- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `row` | `int` | — | Zero-indexed row number. | | `column` | `int` | — | Zero-indexed column, counted in **bytes** from the start of the row. This is `tree_sitter.Point.column` verbatim, and tree-sitter defines it as a byte offset — not characters, and not UTF-16 code units. Measured on a row of the form `x = ''` where `` is a single 4-byte character (an emoji), the string node reports columns `4..10`, identical to its byte range; the character columns would be `4..7` and the UTF-16 columns `4..8`. Anything that builds LSP positions (UTF-16) or editor caret columns (characters) from this field is silently wrong on every row containing a non-ASCII byte, and must re-measure the row against the source text instead. Earlier releases documented this field as UTF-16 code units; that was never what the value contained. | *** #### ProcessConfig [Section titled “ProcessConfig”](#processconfig) Configuration for the `process()` function. Controls which analysis features are enabled and whether chunking is performed. | Field | Type | Default | Description | | ------------------ | ------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `str` | `""` | Language name (required). | | `structure` | `bool` | `True` | Extract structural items (functions, classes, etc.). Default: true. | | `imports` | `bool` | `True` | Extract import statements. Default: true. | | `exports` | `bool` | `True` | Extract export statements. Default: true. | | `comments` | `bool` | `False` | Extract comments. Default: false. | | `docstrings` | `bool` | `False` | Extract docstrings. Default: false. | | `symbols` | `bool` | `False` | Extract symbol definitions. Default: false. | | `diagnostics` | `bool` | `False` | Include parse diagnostics. Default: false. | | `chunk_max_size` | `int \| None` | `None` | Maximum chunk size in bytes. `None` disables chunking. `Some(0)` is rejected by `ProcessConfig.validate` with `Error.InvalidRange`. A zero-sized chunk limit previously produced an empty chunk list and silently discarded the whole source; use `None` to mean “do not chunk”. | | `data_extraction` | `bool` | `False` | Extract hierarchical key/value data tree from data-format files. Default: false. When `True`, `ProcessResult.data` is populated with a `DataNode` tree for supported languages: JSON, YAML, TOML, `.properties`, HCL/HOCON, INI, editorconfig, KDL, CUE, CSV, PSV, PO, nginx config, Caddy config, XML, and DTD. For languages outside this set the field is left as `None`. | | `max_source_bytes` | `int \| None` | `None` | Reject source longer than this many bytes instead of parsing it. Default: `None` (unbounded). Tree-sitter allocates and walks proportionally to input size, so an unbounded parse of attacker-supplied input is a denial-of-service vector. The default stays unbounded for backward compatibility; services handling untrusted input should opt in, e.g. with `RECOMMENDED_MAX_SOURCE_BYTES`. Exceeding the limit fails the call with `Error.InvalidRange` — the source is never silently truncated. | | `parse_timeout_ms` | `int \| None` | `None` | Wall-clock budget for the parse step, in milliseconds. Default: `None` (no timeout). Enforced through tree-sitter’s parse progress callback, which the parser invokes periodically; cancellation is therefore granular to that callback interval rather than exact. A parse that exceeds the budget fails with `Error.ParseTimeout`. | *** #### ProcessResult [Section titled “ProcessResult”](#processresult) Complete analysis result from processing a source file. Contains metrics, structural analysis, imports/exports, comments, docstrings, symbols, diagnostics, and optionally chunked code segments. Fields are populated based on the `ProcessConfig` flags. | Field | Type | Default | Description | | ------------- | ----------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `str` | — | The language name used to parse the source file. | | `metrics` | `FileMetrics` | — | File-level metrics (line counts, byte size, error count). | | `structure` | `list\[StructureItem\]` | `[]` | Top-level structural items (functions, classes, etc.). | | `imports` | `list\[ImportInfo\]` | `[]` | Import statements extracted from the source. | | `exports` | `list\[ExportInfo\]` | `[]` | Export statements extracted from the source. | | `comments` | `list\[CommentInfo\]` | `[]` | Comments extracted from the source. | | `docstrings` | `list\[DocstringInfo\]` | `[]` | Docstrings extracted from the source. | | `symbols` | `list\[SymbolInfo\]` | `[]` | Symbol definitions (variables, types, functions) extracted from the source. | | `diagnostics` | `list\[Diagnostic\]` | `[]` | Parse diagnostics (syntax errors, missing nodes) from tree-sitter. | | `chunks` | `list\[CodeChunk\]` | `[]` | Syntax-aware code chunks produced when chunking is enabled. | | `data` | `DataNode \| None` | `None` | Hierarchical data tree extracted when `config.data_extraction` is `True`. Populated for supported data-format languages (JSON, YAML, TOML, properties, HCL, INI, XML, CSV, and more). `None` when `data_extraction` is `False` (the default) or when the language is not a recognised data format. See `DataNode` for the shape of the returned tree. | *** #### Span [Section titled “Span”](#span) Byte and line/column range in source code. Represents both byte offsets (for slicing) and human-readable line/column positions (for display and diagnostics). | Field | Type | Default | Description | | -------------- | ----- | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `start_byte` | `int` | — | Inclusive start byte offset in the source. | | `end_byte` | `int` | — | Exclusive end byte offset in the source. | | `start_line` | `int` | — | Zero-indexed line number of the span’s start. | | `start_column` | `int` | — | Zero-indexed column of the span’s start, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | | `end_line` | `int` | — | Zero-indexed line number of the span’s end. | | `end_column` | `int` | — | Zero-indexed column of the span’s end, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | *** #### StructureItem [Section titled “StructureItem”](#structureitem) A structural item (function, class, struct, etc.) in source code. | Field | Type | Default | Description | | ------------- | ----------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `kind` | `StructureKind` | `StructureKind.FUNCTION` | The kind of structural item. | | `name` | `str \| None` | `None` | The declared name of the item, if present. | | `visibility` | `str \| None` | `None` | Visibility modifier (e.g., `"pub"`, `"public"`, `"private"`). | | `span` | `Span` | — | Source span covering the entire item declaration. | | `children` | `list\[StructureItem\]` | `[]` | Nested structural items (e.g., methods within a class). | | `decorators` | `list\[str\]` | `[]` | Decorator or attribute names applied to the item. **Reserved: not yet populated.** Always empty, for every language. Recognising a decorator requires per-language grammar knowledge (a Python `decorated_definition` wrapper, Java/C# annotations, Rust attributes each have a different shape), which no extractor here implements yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | | `doc_comment` | `str \| None` | `None` | Documentation comment attached to the item, if any. The text of the comment (or run of comments) immediately preceding the item, with no blank line in between, when that comment is classified as a doc comment. Multiple adjacent single-line doc comments (Rust `///`) are joined with `\n` in source order. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`). `None` for every other language, and for a preceding comment that is not in doc-comment form (a plain `#` comment in Python, Ruby, or Elixir) — Python’s docstring convention is captured separately, as `DocstringInfo`, not through this field. | | `signature` | `str \| None` | `None` | Full signature text of the item (e.g., function parameters and return type). The item’s own source text from its start up to the start of its body (see `StructureItem.body_span`), trimmed of trailing whitespace — for example `fn add(a: i32, b: i32) -> i32` for a Rust function whose body is `{ a + b }`. `None` only when that text is empty, which does not happen for any item `StructureKind` currently reports. Populated for every language and kind this library extracts structure for, since it is derived from `body_span`’s boundary rather than per-language syntax. | | `body_span` | `Span \| None` | `None` | Source span covering only the body of the item, if distinct from the declaration. | *** #### SymbolInfo [Section titled “SymbolInfo”](#symbolinfo) A symbol (variable, function, type, etc.) extracted from source code. | Field | Type | Default | Description | | ----------------- | ------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `str` | — | The name of the symbol. | | `kind` | `SymbolKind` | `SymbolKind.VARIABLE` | The kind of symbol (variable, function, class, etc.). | | `span` | `Span` | — | Source span covering the symbol definition. | | `type_annotation` | `str \| None` | `None` | Explicit type annotation, if present in the source. | | `doc` | `str \| None` | `None` | Documentation comment immediately preceding this symbol, resolved by the same walk `StructureItem.doc_comment` uses (see `doc_comment_at`) — never hard-coded `None`. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`) — the languages whose comment classification recognizes a doc-kind comment. `None` for every other language (e.g. Python, Go, Ruby, which have no doc-kind comment classification), and also `None` when a symbol in a supported language simply has no doc comment immediately above it. | *** #### Tree [Section titled “Tree”](#tree) A parsed syntax tree. Cheap to clone (refcount bump). ##### Methods [Section titled “Methods”](#methods-4) ###### root\_node() [Section titled “root\_node()”](#root_node) Return the root `Node` of this tree. **Signature:** ```python def root_node(self) -> Node ``` **Example:** ```python result = instance.root_node() ``` **Returns:** `Node` ###### walk() [Section titled “walk()”](#walk-1) Return a `TreeCursor` positioned at the root. **Signature:** ```python def walk(self) -> TreeCursor ``` **Example:** ```python result = instance.walk() ``` **Returns:** `TreeCursor` *** #### TreeCursor [Section titled “TreeCursor”](#treecursor) A cursor for traversing a `Tree`. ##### Methods [Section titled “Methods”](#methods-5) ###### node() [Section titled “node()”](#node-1) Return the `Node` at the cursor’s current position. **Signature:** ```python def node(self) -> Node ``` **Example:** ```python result = instance.node() ``` **Returns:** `Node` ###### goto\_first\_child() [Section titled “goto\_first\_child()”](#goto_first_child) Move the cursor to the first child of the current node. Returns `True` if a child existed. **Signature:** ```python def goto_first_child(self) -> bool ``` **Example:** ```python result = instance.goto_first_child() ``` **Returns:** `bool` ###### goto\_parent() [Section titled “goto\_parent()”](#goto_parent) Move the cursor to the parent of the current node. Returns `True` if a parent existed. **Signature:** ```python def goto_parent(self) -> bool ``` **Example:** ```python result = instance.goto_parent() ``` **Returns:** `bool` ###### goto\_next\_sibling() [Section titled “goto\_next\_sibling()”](#goto_next_sibling) Move the cursor to the next sibling of the current node. Returns `True` if a sibling existed. **Signature:** ```python def goto_next_sibling(self) -> bool ``` **Example:** ```python result = instance.goto_next_sibling() ``` **Returns:** `bool` ###### field\_name() [Section titled “field\_name()”](#field_name) Return the field name for the current node, if any. **Signature:** ```python def field_name(self) -> str | None ``` **Example:** ```python result = instance.field_name() ``` **Returns:** `str | None` *** ### Enums [Section titled “Enums”](#enums) #### DataNodeKind [Section titled “DataNodeKind”](#datanodekind) The kind of a data node extracted from a data-format file. Classifies each node in the hierarchical `DataNode` tree returned when `data_extraction` is enabled on `ProcessConfig`. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract) Unit variants serialize as a bare string (`"KeyValue"`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | -------------------------------------------------------------------------------------------------------------------- | | `KEY_VALUE` | A key/value pair or mapping (json/toml/properties/yaml/hcl/cue/kdl pair, or a wrapper “object”/“mapping” container). | | `ELEMENT` | An XML element with a tag name in `key` and attributes in `attributes`. | | `SEQUENCE` | A positional sequence item (JSON array element, YAML block sequence item, CSV/PSV row or cell). | *** #### StructureKind [Section titled “StructureKind”](#structurekind) The kind of structural item found in source code. Categorizes top-level and nested declarations such as functions, classes, structs, enums, traits, and more. Use `Other` for language-specific constructs that do not fit a standard category. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-1) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | ------------------------------------------------------------------------------------------- | | `FUNCTION` | A free-standing or associated function. | | `METHOD` | A method defined inside a class, struct, trait, or impl block. | | `CLASS` | A class definition. | | `STRUCT` | A struct definition. | | `INTERFACE` | An interface or protocol definition. | | `ENUM` | An enum definition. | | `MODULE` | A module or package declaration. | | `TRAIT` | A trait definition. | | `IMPL` | An impl block (Rust) or similar implementation block. | | `NAMESPACE` | A namespace declaration. | | `OTHER` | A language-specific construct that does not fit any standard category. — Fields: `0`: `str` | *** #### CommentKind [Section titled “CommentKind”](#commentkind) The kind of a comment found in source code. Distinguishes between single-line comments, block (multi-line) comments, and documentation comments. | Value | Description | | ------- | --------------------------------------------------------------------- | | `LINE` | A single-line comment (e.g., `// ...` or `# ...`). | | `BLOCK` | A block or multi-line comment using slash-star delimiters. | | `DOC` | A documentation comment such as `/// ...` or slash-double-star block. | *** #### DocstringFormat [Section titled “DocstringFormat”](#docstringformat) The format of a docstring extracted from source code. Identifies the docstring convention used, which varies by language (e.g., Python triple-quoted strings, JSDoc, Rustdoc `///` comments). ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-2) Unit variants serialize as a bare string (`"JSDoc"`); the `Other` variant serializes as a single-keyed object (`{"Other": "rst"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | --------------------- | ----------------------------------------------------------------------------------------------- | | `PYTHON_TRIPLE_QUOTE` | Python triple-quoted string docstring (`"""..."""`). | | `JS_DOC` | JavaScript/TypeScript JSDoc block comment (opens with two stars, closes with star-slash). | | `RUSTDOC` | Rust `///` or `//!` doc comment. | | `GO_DOC` | Go doc comment (a comment block immediately preceding a declaration). | | `JAVA_DOC` | Java Javadoc block comment (opens with two stars, closes with star-slash). | | `OTHER` | A language-specific docstring format not covered by the standard variants. — Fields: `0`: `str` | *** #### ExportKind [Section titled “ExportKind”](#exportkind) The kind of an export statement found in source code. Covers named exports, default exports, and re-exports from other modules. | Value | Description | | ----------- | -------------------------------------------------------------------- | | `NAMED` | A named export (e.g., `export { foo }`). | | `DEFAULT` | A default export (e.g., `export default foo`). | | `RE_EXPORT` | A re-export from another module (e.g., `export { foo } from 'bar'`). | *** #### SymbolKind [Section titled “SymbolKind”](#symbolkind) The kind of a symbol definition found in source code. Categorizes symbol definitions such as variables, constants, functions, classes, types, interfaces, enums, and modules. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-3) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | ------------------------------------------------------------------------ | | `VARIABLE` | A variable binding. | | `CONSTANT` | A constant (immutable binding). | | `FUNCTION` | A function definition. | | `CLASS` | A class definition. | | `TYPE` | A type alias or typedef. | | `INTERFACE` | An interface definition. | | `ENUM` | An enum definition. | | `MODULE` | A module declaration. | | `OTHER` | A symbol kind not covered by the standard variants. — Fields: `0`: `str` | *** #### DiagnosticSeverity [Section titled “DiagnosticSeverity”](#diagnosticseverity) Severity level of a diagnostic produced during parsing. Used to classify parse errors, warnings, and informational messages found in the syntax tree. | Value | Description | | --------- | --------------------------------------------------------------- | | `ERROR` | A parse error (e.g., an `ERROR` or `MISSING` node in the tree). | | `WARNING` | A warning-level diagnostic. | | `INFO` | An informational diagnostic. | *** ### Errors [Section titled “Errors”](#errors) #### Error [Section titled “Error”](#error) Errors that can occur when using the tree-sitter language pack. Covers language lookup failures, parse errors, query errors, and I/O issues. Feature-gated variants are included when `config`, `download`, or related features are enabled. ##### Matching on `Error` [Section titled “Matching on Error”](#matching-on-error) The set of variants is not stable: new failure modes are added in minor releases, and `Io`, `Json`, and `Toml` exist only under certain feature combinations, so the variant set a downstream crate sees depends on which features it enables. Downstream `match`es must therefore carry a `_` arm; `#[non_exhaustive]` makes the compiler enforce that instead of letting a feature change silently break a build. ##### C ABI error codes [Section titled “C ABI error codes”](#c-abi-error-codes) Each variant alef can see carries an explicit `alef(error_code = N)` allocation that becomes a member of the generated `AlefFfiErrorCode` C enum. These numbers are a public ABI contract: **an allocated number is never reused after its variant is removed**, and a variant’s number never changes, because C callers compare against the value, not the name. New variants take the next free number. 0-4 are reserved by alef, so allocation starts at 100. An unannotated variant is emitted as the unknown code rather than as itself, which silently flattens the taxonomy — annotate every new variant. **Base class:** `Error(Exception)` | Exception | Description | | --------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `LanguageNotFoundError(Error)` | The requested language name (or alias) was not found in the registry. | | `DynamicLoadError(Error)` | A dynamic shared library could not be loaded at runtime. | | `NullLanguagePointerError(Error)` | The tree-sitter language function returned a null pointer for the given language name. | | `ParserSetupError(Error)` | The language could not be applied to the parser (e.g., ABI version mismatch). | | `LockPoisonedError(Error)` | An internal `RwLock` or `Mutex` was poisoned by a previous panic. | | `ConfigError(Error)` | A configuration file or value was invalid or could not be applied. | | `ParseFailedError(Error)` | The tree-sitter parser returned no tree for the given source input. | | `ParseTimeoutError(Error)` | The parse was cancelled because it exceeded its configured wall-clock budget. Raised only when a budget is configured — see `ProcessConfig.parse_timeout_ms`, which defaults to `None`. | | `QueryError(Error)` | A tree-sitter query could not be compiled or executed. | | `InvalidRangeError(Error)` | A byte range was invalid (e.g., end before start, or out of bounds). | | `DownloadError(Error)` | A parser download from GitHub releases failed. | | `ChecksumMismatchError(Error)` | The downloaded file’s SHA-256 digest did not match the manifest’s expected value. | | `CacheLockError(Error)` | The cross-process download cache lock file could not be acquired or created. | *** # Ruby API Reference ## Ruby API Reference v1.16.1 [Section titled “Ruby API Reference v1.16.1”](#ruby-api-reference-v1161) ### Functions [Section titled “Functions”](#functions) #### detect\_language\_from\_extension() [Section titled “detect\_language\_from\_extension()”](#detect_language_from_extension) Detect language name from a file extension (without leading dot). Returns `nil` for unrecognized extensions. The match is case-insensitive. **Signature:** ```ruby def self.detect_language_from_extension(ext) ``` **Example:** ```ruby result = detect_language_from_extension("value") ``` **Parameters:** | Name | Type | Required | Description | | ----- | -------- | -------- | ----------- | | `ext` | `String` | Yes | The ext | **Returns:** `String?` *** #### detect\_language\_from\_path() [Section titled “detect\_language\_from\_path()”](#detect_language_from_path) Detect language name from a file path. Extracts the file extension and looks it up. Returns `nil` if the path has no extension or the extension is not recognized. **Signature:** ```ruby def self.detect_language_from_path(path) ``` **Example:** ```ruby result = detect_language_from_path("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `path` | `String` | Yes | Path to the file | **Returns:** `String?` *** #### detect\_language\_from\_content() [Section titled “detect\_language\_from\_content()”](#detect_language_from_content) Detect language name from file content using the shebang line (`#!`). Inspects only the first line of `content`. If it begins with `#!`, the interpreter name is extracted and mapped to a language name. Handles common patterns: * `#!/usr/bin/env python3` → `"python"` * `#!/bin/bash` → `"bash"` * `#!/usr/bin/env node` → `"javascript"` The `-S` flag accepted by some `env` implementations is skipped automatically. Version suffixes (e.g. `python3.11`, `ruby3.2`) are stripped before matching. A leading UTF-8 BOM (`U+FEFF`) is skipped before the `#!` check, so a BOM-prefixed script is still detected by its shebang. Returns `nil` when content does not start with `#!` (after stripping a leading BOM), the shebang is malformed, or the interpreter is not recognised. **Signature:** ```ruby def self.detect_language_from_content(content) ``` **Example:** ```ruby result = detect_language_from_content("value") ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ---------------------- | | `content` | `String` | Yes | The content to process | **Returns:** `String?` *** #### get\_highlights\_query() [Section titled “get\_highlights\_query()”](#get_highlights_query) Get the highlights query for a language, if bundled. Returns the contents of `highlights.scm` as a static string, or `nil` if no highlights query is bundled for this language. **Signature:** ```ruby def self.get_highlights_query(language) ``` **Example:** ```ruby result = get_highlights_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### get\_injections\_query() [Section titled “get\_injections\_query()”](#get_injections_query) Get the injections query for a language, if bundled. Returns the contents of `injections.scm` as a static string, or `nil` if no injections query is bundled for this language. **Signature:** ```ruby def self.get_injections_query(language) ``` **Example:** ```ruby result = get_injections_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### get\_locals\_query() [Section titled “get\_locals\_query()”](#get_locals_query) Get the locals query for a language, if bundled. Returns the contents of `locals.scm` as a static string, or `nil` if no locals query is bundled for this language. **Signature:** ```ruby def self.get_locals_query(language) ``` **Example:** ```ruby result = get_locals_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### get\_tags\_query() [Section titled “get\_tags\_query()”](#get_tags_query) Get the tags query for a language, if bundled. Returns the contents of `tags.scm` as a static string, or `nil` if no tags query is bundled for this language. **Signature:** ```ruby def self.get_tags_query(language) ``` **Example:** ```ruby result = get_tags_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### get\_indents\_query() [Section titled “get\_indents\_query()”](#get_indents_query) Get the indents query for a language, if bundled. Returns the contents of `indents.scm` (used for auto-indentation) as a static string, or `nil` if no indents query is bundled for this language. **Signature:** ```ruby def self.get_indents_query(language) ``` **Example:** ```ruby result = get_indents_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### get\_folds\_query() [Section titled “get\_folds\_query()”](#get_folds_query) Get the folds query for a language, if bundled. Returns the contents of `folds.scm` (used for code folding) as a static string, or `nil` if no folds query is bundled for this language. **Signature:** ```ruby def self.get_folds_query(language) ``` **Example:** ```ruby result = get_folds_query("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### get\_language() [Section titled “get\_language()”](#get_language) Get a tree-sitter `Language` by name using the global registry. Resolves language aliases (e.g., `"shell"` maps to `"bash"`). When the `download` feature is enabled (default), automatically downloads the parser from GitHub releases if not found locally. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.Download` if auto-download fails. **Signature:** ```ruby def self.get_language(name) ``` **Example:** ```ruby result = get_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Language` **Errors:** Raises `Error`. *** #### get\_parser() [Section titled “get\_parser()”](#get_parser) Get a `Parser` pre-configured for the given language. This is a convenience function that calls `get_language` and configures a new parser in one step. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language cannot be applied to the parser. **Signature:** ```ruby def self.get_parser(name) ``` **Example:** ```ruby result = get_parser("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Parser` **Errors:** Raises `Error`. *** #### detect\_language() [Section titled “detect\_language()”](#detect_language) Detect language name from a file path or extension. This compatibility alias matches the pre-Alef Python binding API. **Signature:** ```ruby def self.detect_language(path) ``` **Example:** ```ruby result = detect_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `path` | `String` | Yes | Path to the file | **Returns:** `String?` *** #### available\_languages() [Section titled “available\_languages()”](#available_languages) List all available language names (sorted, deduplicated, includes aliases). Returns names of both statically compiled and dynamically loadable languages, plus any configured aliases. **Signature:** ```ruby def self.available_languages() ``` **Example:** ```ruby result = available_languages() ``` **Returns:** `Array` *** #### has\_language() [Section titled “has\_language()”](#has_language) Check if a language is available by name or alias. Returns `true` if the language can be loaded (statically compiled, dynamically available, or a known alias for one of these). **Signature:** ```ruby def self.has_language(name) ``` **Example:** ```ruby result = has_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Boolean` *** #### language\_count() [Section titled “language\_count()”](#language_count) Return the number of available languages. Includes statically compiled languages, dynamically loadable languages, and aliases. **Signature:** ```ruby def self.language_count() ``` **Example:** ```ruby result = language_count() ``` **Returns:** `Integer` *** #### process() [Section titled “process()”](#process) Process source code and extract file intelligence using the global registry. Parses the source with tree-sitter and extracts metrics, structure, imports, exports, comments, docstrings, symbols, diagnostics, and/or chunks based on the flags set in `ProcessConfig`. **Errors:** Returns `Error.InvalidRange` if the config carries a zero-valued limit or the source exceeds `ProcessConfig.max_source_bytes`, `Error.ParseTimeout` if the parse exceeds `ProcessConfig.parse_timeout_ms`, `Error.LanguageNotFound` if the language is unknown, or `Error.ParseFailed` if parsing yields no tree. **Signature:** ```ruby def self.process(source, config) ``` **Example:** ```ruby result = process("value", ProcessConfig.new) ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `String` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Raises `Error`. *** #### init() [Section titled “init()”](#init) Initialize the language pack with the given configuration. Applies any custom cache directory, then downloads all languages and groups specified in the config. This is the recommended entry point when you want to pre-warm the cache before use. **Errors:** Returns an error if configuration cannot be applied or if downloads fail. **Signature:** ```ruby def self.init(config) ``` **Example:** ```ruby init(PackConfig.new) ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Raises `Error`. *** #### configure() [Section titled “configure()”](#configure) Apply download configuration without downloading anything. Use this to set a custom cache directory before the first call to `get_language` or any download function. Changing the cache dir after languages have been registered has no effect on already-loaded languages. `PackConfig.cache_dir` is a BASE directory, not the final libs path: this crate appends `tree-sitter-language-pack/v{version}/libs` to it, the same suffix applied to the platform default cache directory. In the example below, files actually land under `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`, never directly in `/tmp/my-parsers/`. Call `cache_dir` to read back the resolved, fully-suffixed path. **Errors:** Returns an error if the lock cannot be acquired. **Signature:** ```ruby def self.configure(config) ``` **Example:** ```ruby configure(PackConfig.new) ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Raises `Error`. *** #### download() [Section titled “download()”](#download) Download specific languages to the local cache. Returns the number of distinct languages available after the call. Already compiled or cached languages are included in the count. Aliases are resolved before counting, so `["shell", "bash"]` names one language and returns 1. **Errors:** Returns an error if any language is not available in the manifest or if the download fails. **Signature:** ```ruby def self.download(names) ``` **Example:** ```ruby result = download([]) ``` **Parameters:** | Name | Type | Required | Description | | ------- | --------------- | -------- | ----------- | | `names` | `Array` | Yes | The names | **Returns:** `Integer` **Errors:** Raises `Error`. *** #### prefetch() [Section titled “prefetch()”](#prefetch) Prefetch grammars: download any not already loadable from disk, then load every requested language into the process registry so a subsequent hot loop only parses. Unlike `download()`, this does not trust in-memory availability — it downloads whenever a grammar is not actually loadable from disk (fixing the case where a known-but-not-downloaded grammar is reported present), then resolves and caches every requested language. Call it once, up front, before a parallel workload. **Errors:** Returns `Error.Download` if a required grammar cannot be fetched, or `Error.LanguageNotFound` if a requested name is unknown. **Signature:** ```ruby def self.prefetch(languages) ``` **Example:** ```ruby prefetch([]) ``` **Parameters:** | Name | Type | Required | Description | | ----------- | --------------- | -------- | ------------- | | `languages` | `Array` | Yes | The languages | **Returns:** No return value. **Errors:** Raises `Error`. *** #### download\_all() [Section titled “download\_all()”](#download_all) Download all available languages from the remote manifest. Downloads the platform bundle and extracts every library it contains. Languages that appear in the manifest but are absent from the bundle (e.g. grammars that failed to compile at release time) are silently skipped — they are not treated as an error. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns an error if the manifest cannot be fetched or the bundle download fails. **Signature:** ```ruby def self.download_all() ``` **Example:** ```ruby result = download_all() ``` **Returns:** `Integer` **Errors:** Raises `Error`. *** #### download\_group() [Section titled “download\_group()”](#download_group) Download every language in a named group. Groups are defined by the remote manifest, not by this library, and let you ensure a curated set of related grammars in one call instead of listing each name to `download()`. Already-cached languages are skipped. Call `manifest_groups` to discover the group names the manifest actually defines. The published manifest currently defines a single group, `"all"`; earlier revisions of this documentation advertised `"web"`, `"data"`, and `"systems"`, which the manifest has never contained, so every call following that example failed. Do not hardcode a group name without checking. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns `Error.Download` if the manifest cannot be fetched, if the group is unknown — the message lists the groups the manifest defines — or if any constituent language fails to download. **Signature:** ```ruby def self.download_group(name) ``` **Example:** ```ruby result = download_group("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Integer` **Errors:** Raises `Error`. *** #### manifest\_languages() [Section titled “manifest\_languages()”](#manifest_languages) Return all language names available in the remote manifest (371). Fetches (and caches) the remote manifest to discover the full list of downloadable languages. Use `downloaded_languages` to list what is already cached locally. **Errors:** Returns an error if the manifest cannot be fetched. **Signature:** ```ruby def self.manifest_languages() ``` **Example:** ```ruby result = manifest_languages() ``` **Returns:** `Array` **Errors:** Raises `Error`. *** #### manifest\_groups() [Section titled “manifest\_groups()”](#manifest_groups) Return the names of every language group the remote manifest defines, sorted. Group names are manifest data, not a compile-time constant of this library, so this is the only reliable way to learn what `download_group` and `PackConfig.groups` accept. The published manifest currently defines just `"all"`. **Errors:** Returns `Error.Download` if the manifest cannot be fetched. **Signature:** ```ruby def self.manifest_groups() ``` **Example:** ```ruby result = manifest_groups() ``` **Returns:** `Array` **Errors:** Raises `Error`. *** #### downloaded\_languages() [Section titled “downloaded\_languages()”](#downloaded_languages) Return languages that are already downloaded and cached locally. Does not perform any network requests. Returns an empty list if the cache directory does not exist or cannot be read. **Signature:** ```ruby def self.downloaded_languages() ``` **Example:** ```ruby result = downloaded_languages() ``` **Returns:** `Array` *** #### clean\_cache() [Section titled “clean\_cache()”](#clean_cache) Delete all cached parser shared libraries. Resets the cache registration so the next call to `get_language` or a download function will re-register the (now empty) cache directory. **Errors:** Returns an error if the cache directory cannot be removed. **Signature:** ```ruby def self.clean_cache() ``` **Example:** ```ruby clean_cache() ``` **Returns:** No return value. **Errors:** Raises `Error`. *** #### cache\_dir() [Section titled “cache\_dir()”](#cache_dir) Return the effective cache directory path. This is `{base}/tree-sitter-language-pack/v{version}/libs/`, where `{base}` is either the custom BASE directory set via `configure` / `init` (`PackConfig.cache_dir`) or the platform default cache directory — both are suffixed identically, so a custom `cache_dir` is never used as the final libs path. The default resolves to `~/.cache/tree-sitter-language-pack/v{version}/libs/` on a typical Unix system. **Errors:** Returns an error if no cache directory can be resolved: `version` is somehow invalid, or (with no custom `cache_dir` configured) the platform reports none and `TREE_SITTER_LANGUAGE_PACK_CACHE_DIR` is unset. This crate no longer falls back to the temporary directory for the latter case — see #101 H2. **Signature:** ```ruby def self.cache_dir() ``` **Example:** ```ruby result = cache_dir() ``` **Returns:** `String` **Errors:** Raises `Error`. *** ### Types [Section titled “Types”](#types) #### ByteRange [Section titled “ByteRange”](#byterange) A byte range — start (inclusive) to end (exclusive). | Field | Type | Default | Description | | ------- | --------- | ------- | ---------------------------- | | `start` | `Integer` | — | Inclusive start byte offset. | | `end` | `Integer` | — | Exclusive end byte offset. | *** #### ChunkContext [Section titled “ChunkContext”](#chunkcontext) Metadata for a single chunk of source code. | Field | Type | Default | Description | | ----------------- | ---------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String` | — | Language name used to parse this chunk. | | `chunk_index` | `Integer` | — | Zero-indexed position of this chunk within the file’s chunk list. | | `total_chunks` | `Integer` | — | Total number of chunks the file was split into. | | `node_types` | `Array` | `[]` | Tree-sitter node kinds that appear at the top level of this chunk. | | `context_path` | `Array` | `[]` | Hierarchical path of enclosing structural items (e.g., `["MyClass", "my_method"]`). | | `symbols_defined` | `Array` | `[]` | Names of symbols defined within this chunk. | | `comments` | `Array` | `[]` | Comments contained within this chunk. | | `docstrings` | `Array` | `[]` | Docstrings contained within this chunk. Populated only for Python — the same language for which `ProcessResult.docstrings` is populated, and by the same classifier. Always empty for every other language. | | `has_error_nodes` | `Boolean` | — | Whether this chunk contains any tree-sitter error nodes. | *** #### CodeChunk [Section titled “CodeChunk”](#codechunk) A chunk of source code with rich metadata. | Field | Type | Default | Description | | ------------ | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `content` | `String` | — | The raw source text of this chunk. | | `start_byte` | `Integer` | — | Inclusive start byte offset of this chunk in the original source. | | `end_byte` | `Integer` | — | Exclusive end byte offset of this chunk in the original source. | | `start_line` | `Integer` | — | Zero-indexed start line of this chunk. | | `end_line` | `Integer` | — | Zero-indexed row of the last byte actually included in this chunk (inclusive — the same row a `Span.end_line` would report for a node ending on that byte). Computed the same way regardless of whether the source has a trailing newline: it is always the row of `end_byte - 1`, never a phantom row past the file’s real content. | | `metadata` | `ChunkContext` | — | Contextual metadata about this chunk. | *** #### CommentInfo [Section titled “CommentInfo”](#commentinfo) A comment extracted from source code. | Field | Type | Default | Description | | ----------------- | ------------- | ------- | ----------------------------------------------------------------- | | `text` | `String` | — | The raw text content of the comment. | | `kind` | `CommentKind` | `:line` | The kind of comment (line, block, or doc). | | `span` | `Span` | — | Source span covering the comment. | | `associated_node` | `String?` | `nil` | Name of the syntax node this comment is directly associated with. | *** #### DataAttribute [Section titled “DataAttribute”](#dataattribute) An XML-style attribute attached to an `Element` node. Populated only for `DataNodeKind.Element`; always empty for `KeyValue` and `Sequence` nodes. | Field | Type | Default | Description | | ------- | -------- | ------- | --------------------------------------------------------------- | | `name` | `String` | — | Attribute name (e.g. `"class"`, `"href"`). | | `value` | `String` | — | Attribute value as a raw string (quotes stripped). | | `span` | `Span` | — | Source span covering the entire `name="value"` attribute token. | *** #### DataNode [Section titled “DataNode”](#datanode) A node in the hierarchical data tree produced by data-format extraction. When `ProcessConfig.data_extraction` is `true`, `ProcessResult.data` is populated with a root `DataNode` whose `children` mirror the structure of the parsed file. The `kind` field determines which other fields are meaningful: | `kind` | `key` | `value` | `attributes` | `children` | | ---------- | ------------------------- | ------------ | ------------ | -------------- | | `KeyValue` | key / mapping key / index | leaf value | empty | nested map | | `Element` | XML tag name | text content | XML attrs | child elements | | `Sequence` | positional index (`"0"`) | leaf value | empty | sub-items | | Field | Type | Default | Description | | ------------ | ---------------------- | ------------ | ---------------------------------------------------------------------------------------------------- | | `kind` | `DataNodeKind` | `:key_value` | Whether this node is a key/value pair, XML element, or sequence item. | | `key` | `String?` | `nil` | Key, attribute name, tag name, or positional index (`"0"`, `"1"`, …). `nil` at the document root. | | `value` | `String?` | `nil` | Leaf scalar value, if any. `nil` for containers (objects, arrays, XML elements with child elements). | | `attributes` | `Array` | `[]` | Attributes on element-shape nodes (XML `STag` attributes). Empty for all other kinds. | | `children` | `Array` | `[]` | Children for nested containers and XML element bodies. | | `span` | `Span` | — | Source span covering this node in the original source file. | *** #### Diagnostic [Section titled “Diagnostic”](#diagnostic) A diagnostic (syntax error, missing node, etc.) from parsing. | Field | Type | Default | Description | | ---------- | -------------------- | -------- | ---------------------------------------------- | | `message` | `String` | — | Human-readable description of the diagnostic. | | `severity` | `DiagnosticSeverity` | `:error` | Severity of the diagnostic. | | `span` | `Span` | — | Source span where the diagnostic was detected. | *** #### DocSection [Section titled “DocSection”](#docsection) A section within a docstring (e.g., Args, Returns, Raises). | Field | Type | Default | Description | | ------------- | --------- | ------- | ------------------------------------------------------- | | `kind` | `String` | — | Section kind (e.g., `"args"`, `"returns"`, `"raises"`). | | `name` | `String?` | `nil` | Parameter or return value name, if applicable. | | `description` | `String` | — | Description text for this section. | *** #### DocstringInfo [Section titled “DocstringInfo”](#docstringinfo) A docstring extracted from source code. | Field | Type | Default | Description | | ----------------- | ------------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | `String` | — | The raw text of the docstring. | | `format` | `DocstringFormat` | `:python_triple_quote` | The docstring format (Python, JSDoc, Rustdoc, etc.). | | `span` | `Span` | — | Source span covering the docstring. | | `associated_item` | `String?` | `nil` | Name of the item this docstring documents. | | `parsed_sections` | `Array` | `[]` | Parsed sections of the docstring (Args, Returns, Raises, etc.). **Reserved: not yet populated.** Always empty, for every `DocstringFormat`. Parsing a docstring body into sections requires implementing each convention’s own layout (Google/NumPy/reST style for Python, `@param`/`@returns` for JSDoc/Javadoc, and so on), which no extractor here does yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | *** #### DownloadManager [Section titled “DownloadManager”](#downloadmanager) Manages downloading and caching of pre-built parser shared libraries. ##### Methods [Section titled “Methods”](#methods) ###### new() [Section titled “new()”](#new) Create a new download manager for the given version. **Errors:** Returns `Error.Download` if `version` is empty, contains a path separator or `..`, or contains a character outside `[A-Za-z0-9.+-]` — see `validate_version` — or if no cache directory can be resolved (see `Self.default_cache_dir`). **Signature:** ```ruby def self.new(version) ``` **Example:** ```ruby result = DownloadManager.new("value") ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ----------- | | `version` | `String` | Yes | The version | **Returns:** `DownloadManager` **Errors:** Raises `Error`. ###### installed\_languages() [Section titled “installed\_languages()”](#installed_languages) List languages that are already downloaded and cached. Derived from the on-disk cache filenames, one canonical name per file, plus every alias that resolves to it (via `aliases_for`) — so this list agrees with the user-facing `LanguageRegistry.available_languages` about which names are “available”; both report `"shell"` once `bash` is cached, for example. A previous version reported canonical names only, which could never agree with `available_languages()`. See #107. Returns an empty list if the cache directory does not exist. If it exists but cannot be read (e.g. a permission error), also returns an empty list — changing this to a `Result` would be a breaking change across every language binding — but logs a `tracing.warn!` so the failure is not silently indistinguishable from “nothing installed”. **Signature:** ```ruby def installed_languages() ``` **Example:** ```ruby result = instance.installed_languages() ``` **Returns:** `Array` ###### download\_all\_best\_effort() [Section titled “download\_all\_best\_effort()”](#download_all_best_effort) Download the platform bundle and extract every library file it contains. Unlike `Self.ensure_languages`, this does not check the manifest language list against archive contents — it simply extracts all `.so`/`.dylib`/`.dll` files from the bundle. Languages in the manifest that are missing from the archive are silently ignored rather than returning an error. Returns the number of library files extracted (including those already cached). **Signature:** ```ruby def download_all_best_effort() ``` **Example:** ```ruby result = instance.download_all_best_effort() ``` **Returns:** `Integer` **Errors:** Raises `Error`. ###### clean\_cache() [Section titled “clean\_cache()”](#clean_cache-1) Remove all cached parser libraries. Acquires the cross-process lock so `clean_cache` cannot race a concurrent downloader (avoids Windows sharing-violation errors against an in-flight bundle write). The `.download.lock` file itself is **not** removed — it is permanent infrastructure; deleting it could allow a concurrent process that already opened the file to continue holding a stale lock handle while a new process opens a fresh inode, breaking the mutual-exclusion guarantee. **Signature:** ```ruby def clean_cache() ``` **Example:** ```ruby instance.clean_cache() ``` **Returns:** No return value. **Errors:** Raises `Error`. *** #### ExportInfo [Section titled “ExportInfo”](#exportinfo) An export statement extracted from source code. | Field | Type | Default | Description | | ------ | ------------ | -------- | -------------------------------------------------- | | `name` | `String` | — | The exported name. | | `kind` | `ExportKind` | `:named` | The kind of export (named, default, or re-export). | | `span` | `Span` | — | Source span covering the export statement. | *** #### FileMetrics [Section titled “FileMetrics”](#filemetrics) Aggregate metrics for a source file. | Field | Type | Default | Description | | --------------- | --------- | ------- | -------------------------------------------------------------- | | `total_lines` | `Integer` | — | Total number of lines (including blank and comment lines). | | `code_lines` | `Integer` | — | Number of lines containing non-blank, non-comment source code. | | `comment_lines` | `Integer` | — | Number of lines that are entirely comments. | | `blank_lines` | `Integer` | — | Number of blank (whitespace-only) lines. | | `total_bytes` | `Integer` | — | Total byte length of the source file. | | `node_count` | `Integer` | — | Total number of nodes in the syntax tree. | | `error_count` | `Integer` | — | Number of error nodes in the syntax tree (parse errors). | | `max_depth` | `Integer` | — | Maximum nesting depth reached in the syntax tree. | *** #### ImportInfo [Section titled “ImportInfo”](#importinfo) An import statement extracted from source code. | Field | Type | Default | Description | | ------------- | --------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `source` | `String` | — | The module or path being imported from. | | `items` | `Array` | `[]` | Specific names imported from the source module. For `import a, b` / `from m import a, b`, every entry’s base name (never the alias). For a JavaScript/TypeScript named-imports clause (`import { a, b as c } from 'm'`), every specifier’s original name. Populated for Python and JavaScript/TypeScript only. Always empty for every other language this library recognises import statements for — Rust, Go, Java, Kotlin, and Elixir (`import`/`alias`/`require`/`use`) — and for a JS/TS namespace import (`import * as ns`) or default import (`import x from 'm'`), neither of which names individual items. | | `alias` | `String?` | `nil` | Alias assigned to the import (e.g., `import numpy as np`). Populated for Python’s single-name form (`import numpy as np`, `from m import a as b`) and JavaScript/TypeScript’s namespace form (`import * as ns from 'm'`) or a named-imports clause naming exactly one specifier (`import { a as b } from 'm'`). `nil` for Rust, Go, Java, Kotlin, and Elixir (which has its own `as:` alias option on `alias` directives, not yet extracted here) — and for a Python statement that aliases several names at once (`import os, sys as s`), where there is no single alias to report for the statement as a whole, so only `items` is populated for it. | | `is_wildcard` | `Boolean` | — | Whether this is a wildcard import (e.g., `import *` or `use foo.*`). Detected from the syntax tree — a dedicated wildcard node (`wildcard_import` in Python, `use_wildcard` in Rust) or a bare `*` token outside of string-literal content — not by searching the import’s source text for a `*` character, so a glob in an import path string (`import a from './glob*.js'`) is not mistaken for one. | | `span` | `Span` | — | Source span covering the import statement. | *** #### Language [Section titled “Language”](#language) *** #### LanguageRegistry [Section titled “LanguageRegistry”](#languageregistry) Thread-safe registry of tree-sitter language parsers. Manages both statically compiled and dynamically loaded language grammars. Use `LanguageRegistry.new()` for the default registry, or access the global instance via the module-level convenience functions (`get_language`, `available_languages`, etc.). ##### Methods [Section titled “Methods”](#methods-1) ###### new() [Section titled “new()”](#new-1) Create a new registry populated with all statically compiled languages. When the `dynamic-loading` feature is enabled, the registry also knows about dynamically loadable grammars and will load them on demand. **Signature:** ```ruby def self.new() ``` **Example:** ```ruby result = LanguageRegistry.new() ``` **Returns:** `LanguageRegistry` ###### get\_language() [Section titled “get\_language()”](#get_language-1) Get a tree-sitter `Language` by name. Resolves aliases (e.g., `"shell"` -> `"bash"`, `"makefile"` -> `"make"`), then looks up the language in the static table. When the `dynamic-loading` feature is enabled, falls back to loading a shared library on demand. **Errors:** Returns `Error.LanguageNotFound` if the name (after alias resolution) does not match any known grammar. **Signature:** ```ruby def get_language(name) ``` **Example:** ```ruby result = instance.get_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Language` **Errors:** Raises `Error`. ###### available\_languages() [Section titled “available\_languages()”](#available_languages-1) List all available language names, sorted and deduplicated. Includes statically compiled languages, dynamically loadable languages (if the `dynamic-loading` feature is enabled), and all configured aliases. **Signature:** ```ruby def available_languages() ``` **Example:** ```ruby result = instance.available_languages() ``` **Returns:** `Array` ###### has\_parser() [Section titled “has\_parser()”](#has_parser) Check whether this language can be parsed right now, without downloading. Resolves aliases, then answers from exactly the lookup `get_language` performs: the statically compiled table, the already-loaded dynamic grammars, and the parser shared libraries present in the primary and extra (download-cache) library directories. It never performs network I/O. A previous implementation consulted only the statically compiled table. That table is empty in every build that does not set `TSLP_LANGUAGES`, so the function answered `false` for languages this registry parses perfectly well. Contrast `has_language`, which is also `true` for a grammar that is merely *known to the manifest* and would have to be downloaded first. The pair distinguishes “we can parse it offline, now” from “we recognise the name”. The first `true` answer for a dynamic grammar loads its shared library: loading is the only way to know the grammar is usable, since a truncated or wrong-architecture library exists on disk but cannot parse. Loads are cached process-wide, so repeat calls are cheap. **Signature:** ```ruby def has_parser(name) ``` **Example:** ```ruby result = instance.has_parser("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Boolean` ###### has\_language() [Section titled “has\_language()”](#has_language-1) Check whether a language is available by name or alias. Returns `true` if the language can be loaded, either from the static table or from a dynamic library on disk. Every branch is one more way to answer `true`, so they are ordered cheapest-first and the filesystem is only consulted once every in-memory source has said no. Probing the loaded-grammar map and the manifest ahead of the `stat` calls is what keeps this off the syscall path for the languages a process actually uses. **Signature:** ```ruby def has_language(name) ``` **Example:** ```ruby result = instance.has_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Boolean` ###### language\_count() [Section titled “language\_count()”](#language_count-1) Return the total number of available languages (including aliases). Counts the same set `available_languages` lists, without materialising or sorting it. **Signature:** ```ruby def language_count() ``` **Example:** ```ruby result = instance.language_count() ``` **Returns:** `Integer` ###### process() [Section titled “process()”](#process-1) Parse source code and extract file intelligence based on config in a single pass. **Errors:** Returns `Error.InvalidRange` if the config is invalid (see `ProcessConfig.validate`) or if the source exceeds the configured `max_source_bytes`; `Error.LanguageNotFound` if the language is unknown; or `Error.ParseFailed` if parsing produces no tree. **Signature:** ```ruby def process(source, config) ``` **Example:** ```ruby result = instance.process("value", ProcessConfig.new) ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `String` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Raises `Error`. *** #### Node [Section titled “Node”](#node) A single syntax node within a `Tree`. Nodes hold a strong reference to their parent tree so they remain valid regardless of how the tree is moved or stored at the FFI boundary. ##### Methods [Section titled “Methods”](#methods-2) ###### kind() [Section titled “kind()”](#kind) Return the node’s kind name (e.g. `"function_definition"`). **Signature:** ```ruby def kind() ``` **Example:** ```ruby result = instance.kind() ``` **Returns:** `String` ###### kind\_id() [Section titled “kind\_id()”](#kind_id) Return the node’s numeric kind ID. Tree-sitter assigns a stable `u16` ID to every node kind in a grammar (e.g. `"function_definition" → 42`). Comparing `kind_id()` is cheaper than comparing the string `kind()` in tight AST loops. **Signature:** ```ruby def kind_id() ``` **Example:** ```ruby result = instance.kind_id() ``` **Returns:** `Integer` ###### start\_byte() [Section titled “start\_byte()”](#start_byte) Return the inclusive start byte offset of this node. **Signature:** ```ruby def start_byte() ``` **Example:** ```ruby result = instance.start_byte() ``` **Returns:** `Integer` ###### end\_byte() [Section titled “end\_byte()”](#end_byte) Return the exclusive end byte offset of this node. **Signature:** ```ruby def end_byte() ``` **Example:** ```ruby result = instance.end_byte() ``` **Returns:** `Integer` ###### byte\_range() [Section titled “byte\_range()”](#byte_range) Return the node’s byte range as a `ByteRange`. Callers should slice their own source bytes — this is a zero-copy text accessor. **Signature:** ```ruby def byte_range() ``` **Example:** ```ruby result = instance.byte_range() ``` **Returns:** `ByteRange` ###### start\_position() [Section titled “start\_position()”](#start_position) Return the start `Point` (row, column). **Signature:** ```ruby def start_position() ``` **Example:** ```ruby result = instance.start_position() ``` **Returns:** `Point` ###### end\_position() [Section titled “end\_position()”](#end_position) Return the end `Point` (row, column). **Signature:** ```ruby def end_position() ``` **Example:** ```ruby result = instance.end_position() ``` **Returns:** `Point` ###### is\_named() [Section titled “is\_named()”](#is_named) True when this node is named (not punctuation/whitespace). **Signature:** ```ruby def is_named() ``` **Example:** ```ruby result = instance.is_named() ``` **Returns:** `Boolean` ###### is\_error() [Section titled “is\_error()”](#is_error) True when this is an error node. **Signature:** ```ruby def is_error() ``` **Example:** ```ruby result = instance.is_error() ``` **Returns:** `Boolean` ###### is\_missing() [Section titled “is\_missing()”](#is_missing) True when this is a missing-token node. **Signature:** ```ruby def is_missing() ``` **Example:** ```ruby result = instance.is_missing() ``` **Returns:** `Boolean` ###### is\_extra() [Section titled “is\_extra()”](#is_extra) True when this is an “extra” node (e.g. a comment). **Signature:** ```ruby def is_extra() ``` **Example:** ```ruby result = instance.is_extra() ``` **Returns:** `Boolean` ###### has\_error() [Section titled “has\_error()”](#has_error) True when this node or any descendant is an error. **Signature:** ```ruby def has_error() ``` **Example:** ```ruby result = instance.has_error() ``` **Returns:** `Boolean` ###### parent() [Section titled “parent()”](#parent) Return this node’s parent, if any. **Signature:** ```ruby def parent() ``` **Example:** ```ruby result = instance.parent() ``` **Returns:** `Node?` ###### child() [Section titled “child()”](#child) Return the i-th child of this node, if any. **Signature:** ```ruby def child(index) ``` **Example:** ```ruby result = instance.child(42) ``` **Parameters:** | Name | Type | Required | Description | | ------- | --------- | -------- | ----------- | | `index` | `Integer` | Yes | The index | **Returns:** `Node?` ###### child\_count() [Section titled “child\_count()”](#child_count) Total number of children (including unnamed). **Signature:** ```ruby def child_count() ``` **Example:** ```ruby result = instance.child_count() ``` **Returns:** `Integer` ###### named\_child() [Section titled “named\_child()”](#named_child) Return the i-th named child of this node, if any. **Signature:** ```ruby def named_child(index) ``` **Example:** ```ruby result = instance.named_child(42) ``` **Parameters:** | Name | Type | Required | Description | | ------- | --------- | -------- | ----------- | | `index` | `Integer` | Yes | The index | **Returns:** `Node?` ###### named\_child\_count() [Section titled “named\_child\_count()”](#named_child_count) Number of named children of this node. **Signature:** ```ruby def named_child_count() ``` **Example:** ```ruby result = instance.named_child_count() ``` **Returns:** `Integer` ###### child\_by\_field\_name() [Section titled “child\_by\_field\_name()”](#child_by_field_name) Look up a child by its grammar-defined field name. **Signature:** ```ruby def child_by_field_name(name) ``` **Example:** ```ruby result = instance.child_by_field_name("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Node?` ###### to\_sexp() [Section titled “to\_sexp()”](#to_sexp) Return the S-expression form of this node’s subtree. **Signature:** ```ruby def to_sexp() ``` **Example:** ```ruby result = instance.to_sexp() ``` **Returns:** `String` ###### walk() [Section titled “walk()”](#walk) Return a `TreeCursor` positioned at this node. **Signature:** ```ruby def walk() ``` **Example:** ```ruby result = instance.walk() ``` **Returns:** `TreeCursor` *** #### PackConfig [Section titled “PackConfig”](#packconfig) Configuration for the tree-sitter language pack. Controls cache directory and which languages to pre-download. Can be loaded from a TOML file, constructed programmatically, or passed as a dict/object from language bindings. | Field | Type | Default | Description | | ----------- | ---------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cache_dir` | `String?` | `nil` | Override the BASE directory the parser cache lives under. This is a base, not the final library path: the crate appends `tree-sitter-language-pack/v{version}/libs` to it, exactly as it does to the platform default. So `cache_dir = "/tmp/my-parsers"` resolves to `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`. The suffix is not cosmetic. It keeps the whole cache tree — manifest, bundles and lock file included — inside a directory this library owns and versions. Earlier releases used this path verbatim, which put those files in the configured directory’s PARENT and let a cache built by one crate version be reused by another. Default base: the platform cache dir, e.g. `~/.cache` on Linux. | | `languages` | `Array?` | `[]` | Languages to pre-download on init. Each entry is a language name (e.g. `"python"`, `"rust"`). | | `groups` | `Array?` | `[]` | Language groups to pre-download. Group names come from the remote manifest, so the valid set is not fixed by this library; the published manifest currently defines only `"all"`. Call `manifest_groups` to enumerate them. An unknown name makes `init` fail. | *** #### Parser [Section titled “Parser”](#parser) A tree-sitter parser configured for one language at a time. ##### Methods [Section titled “Methods”](#methods-3) ###### new() [Section titled “new()”](#new-2) Construct a new parser with no language set and no parse limits. Call `Parser.set_language` before parsing. Limits are opt-in via `set_max_source_bytes` and `set_parse_timeout_ms`; both default to unbounded so that existing callers are unaffected. **Signature:** ```ruby def self.new() ``` **Example:** ```ruby result = Parser.new() ``` **Returns:** `Parser` ###### set\_max\_source\_bytes() [Section titled “set\_max\_source\_bytes()”](#set_max_source_bytes) Refuse to parse sources longer than `max_bytes`. `nil` (the default) means no limit. Over-limit input makes `parse` and `parse_bytes` return `nil` after emitting a `WARN`; input is never silently truncated. See `RECOMMENDED_MAX_SOURCE_BYTES`. **Signature:** ```ruby def set_max_source_bytes(max_bytes) ``` **Example:** ```ruby instance.set_max_source_bytes(max_bytes: 42) ``` **Parameters:** | Name | Type | Required | Description | | ----------- | ---------- | -------- | ------------- | | `max_bytes` | `Integer?` | No | The max bytes | **Returns:** No return value. ###### set\_parse\_timeout\_ms() [Section titled “set\_parse\_timeout\_ms()”](#set_parse_timeout_ms) Cancel a parse that exceeds `timeout_ms` milliseconds of wall clock. `nil` (the default) means no budget. Cancellation runs through tree-sitter’s parse progress callback, so it is granular to that callback’s interval rather than exact. See `RECOMMENDED_PARSE_TIMEOUT_MS`. **Signature:** ```ruby def set_parse_timeout_ms(timeout_ms) ``` **Example:** ```ruby instance.set_parse_timeout_ms(timeout_ms: 42) ``` **Parameters:** | Name | Type | Required | Description | | ------------ | ---------- | -------- | -------------- | | `timeout_ms` | `Integer?` | No | The timeout ms | **Returns:** No return value. ###### set\_language() [Section titled “set\_language()”](#set_language) Configure the parser to use the language identified by name (e.g. `"python"`). Resolves the language through the global registry — auto-downloading if necessary, when the `download` feature is enabled. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language ABI is incompatible. **Signature:** ```ruby def set_language(name) ``` **Example:** ```ruby instance.set_language("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** No return value. **Errors:** Raises `Error`. ###### parse() [Section titled “parse()”](#parse) Parse a UTF-8 source string. Returns `nil` if no language is set, if the parse was cancelled by the configured timeout, or if the source exceeds the configured size limit. Each non-parse outcome is logged, so an empty result is never silent. ###### Concurrency [Section titled “Concurrency”](#concurrency) Parsing runs fully in parallel across threads for almost every language — no lock is taken. The exception is the small set of grammars whose external scanner keeps mutable process-global state (currently just `properties`): parses of that language are serialized against each other through an internal per-language lock, so that concurrent threads can’t corrupt shared scanner state. Every other language is unaffected by that lock and never waits on it. **Signature:** ```ruby def parse(source) ``` **Example:** ```ruby result = instance.parse("value") ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------- | -------- | ----------- | | `source` | `String` | Yes | The source | **Returns:** `Tree?` ###### parse\_bytes() [Section titled “parse\_bytes()”](#parse_bytes) Parse a raw byte slice. Same outcomes as `parse`, including the concurrency behaviour documented there. **Signature:** ```ruby def parse_bytes(source) ``` **Example:** ```ruby result = instance.parse_bytes("data") ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------- | -------- | ----------- | | `source` | `String` | Yes | The source | **Returns:** `Tree?` ###### reset() [Section titled “reset()”](#reset) Reset internal state. The next call to `parse` will not be incremental. **Signature:** ```ruby def reset() ``` **Example:** ```ruby instance.reset() ``` **Returns:** No return value. *** #### Point [Section titled “Point”](#point) A source position — row + column, zero-indexed. | Field | Type | Default | Description | | -------- | --------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `row` | `Integer` | — | Zero-indexed row number. | | `column` | `Integer` | — | Zero-indexed column, counted in **bytes** from the start of the row. This is `tree_sitter.Point.column` verbatim, and tree-sitter defines it as a byte offset — not characters, and not UTF-16 code units. Measured on a row of the form `x = ''` where `` is a single 4-byte character (an emoji), the string node reports columns `4..10`, identical to its byte range; the character columns would be `4..7` and the UTF-16 columns `4..8`. Anything that builds LSP positions (UTF-16) or editor caret columns (characters) from this field is silently wrong on every row containing a non-ASCII byte, and must re-measure the row against the source text instead. Earlier releases documented this field as UTF-16 code units; that was never what the value contained. | *** #### ProcessConfig [Section titled “ProcessConfig”](#processconfig) Configuration for the `process()` function. Controls which analysis features are enabled and whether chunking is performed. | Field | Type | Default | Description | | ------------------ | ---------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String` | `""` | Language name (required). | | `structure` | `Boolean` | `true` | Extract structural items (functions, classes, etc.). Default: true. | | `imports` | `Boolean` | `true` | Extract import statements. Default: true. | | `exports` | `Boolean` | `true` | Extract export statements. Default: true. | | `comments` | `Boolean` | `false` | Extract comments. Default: false. | | `docstrings` | `Boolean` | `false` | Extract docstrings. Default: false. | | `symbols` | `Boolean` | `false` | Extract symbol definitions. Default: false. | | `diagnostics` | `Boolean` | `false` | Include parse diagnostics. Default: false. | | `chunk_max_size` | `Integer?` | `nil` | Maximum chunk size in bytes. `nil` disables chunking. `Some(0)` is rejected by `ProcessConfig.validate` with `Error.InvalidRange`. A zero-sized chunk limit previously produced an empty chunk list and silently discarded the whole source; use `nil` to mean “do not chunk”. | | `data_extraction` | `Boolean` | `false` | Extract hierarchical key/value data tree from data-format files. Default: false. When `true`, `ProcessResult.data` is populated with a `DataNode` tree for supported languages: JSON, YAML, TOML, `.properties`, HCL/HOCON, INI, editorconfig, KDL, CUE, CSV, PSV, PO, nginx config, Caddy config, XML, and DTD. For languages outside this set the field is left as `nil`. | | `max_source_bytes` | `Integer?` | `nil` | Reject source longer than this many bytes instead of parsing it. Default: `nil` (unbounded). Tree-sitter allocates and walks proportionally to input size, so an unbounded parse of attacker-supplied input is a denial-of-service vector. The default stays unbounded for backward compatibility; services handling untrusted input should opt in, e.g. with `RECOMMENDED_MAX_SOURCE_BYTES`. Exceeding the limit fails the call with `Error.InvalidRange` — the source is never silently truncated. | | `parse_timeout_ms` | `Integer?` | `nil` | Wall-clock budget for the parse step, in milliseconds. Default: `nil` (no timeout). Enforced through tree-sitter’s parse progress callback, which the parser invokes periodically; cancellation is therefore granular to that callback interval rather than exact. A parse that exceeds the budget fails with `Error.ParseTimeout`. | *** #### ProcessResult [Section titled “ProcessResult”](#processresult) Complete analysis result from processing a source file. Contains metrics, structural analysis, imports/exports, comments, docstrings, symbols, diagnostics, and optionally chunked code segments. Fields are populated based on the `ProcessConfig` flags. | Field | Type | Default | Description | | ------------- | ---------------------- | ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String` | — | The language name used to parse the source file. | | `metrics` | `FileMetrics` | — | File-level metrics (line counts, byte size, error count). | | `structure` | `Array` | `[]` | Top-level structural items (functions, classes, etc.). | | `imports` | `Array` | `[]` | Import statements extracted from the source. | | `exports` | `Array` | `[]` | Export statements extracted from the source. | | `comments` | `Array` | `[]` | Comments extracted from the source. | | `docstrings` | `Array` | `[]` | Docstrings extracted from the source. | | `symbols` | `Array` | `[]` | Symbol definitions (variables, types, functions) extracted from the source. | | `diagnostics` | `Array` | `[]` | Parse diagnostics (syntax errors, missing nodes) from tree-sitter. | | `chunks` | `Array` | `[]` | Syntax-aware code chunks produced when chunking is enabled. | | `data` | `DataNode?` | `nil` | Hierarchical data tree extracted when `config.data_extraction` is `true`. Populated for supported data-format languages (JSON, YAML, TOML, properties, HCL, INI, XML, CSV, and more). `nil` when `data_extraction` is `false` (the default) or when the language is not a recognised data format. See `DataNode` for the shape of the returned tree. | *** #### Span [Section titled “Span”](#span) Byte and line/column range in source code. Represents both byte offsets (for slicing) and human-readable line/column positions (for display and diagnostics). | Field | Type | Default | Description | | -------------- | --------- | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `start_byte` | `Integer` | — | Inclusive start byte offset in the source. | | `end_byte` | `Integer` | — | Exclusive end byte offset in the source. | | `start_line` | `Integer` | — | Zero-indexed line number of the span’s start. | | `start_column` | `Integer` | — | Zero-indexed column of the span’s start, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | | `end_line` | `Integer` | — | Zero-indexed line number of the span’s end. | | `end_column` | `Integer` | — | Zero-indexed column of the span’s end, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | *** #### StructureItem [Section titled “StructureItem”](#structureitem) A structural item (function, class, struct, etc.) in source code. | Field | Type | Default | Description | | ------------- | ---------------------- | ----------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `kind` | `StructureKind` | `:function` | The kind of structural item. | | `name` | `String?` | `nil` | The declared name of the item, if present. | | `visibility` | `String?` | `nil` | Visibility modifier (e.g., `"pub"`, `"public"`, `"private"`). | | `span` | `Span` | — | Source span covering the entire item declaration. | | `children` | `Array` | `[]` | Nested structural items (e.g., methods within a class). | | `decorators` | `Array` | `[]` | Decorator or attribute names applied to the item. **Reserved: not yet populated.** Always empty, for every language. Recognising a decorator requires per-language grammar knowledge (a Python `decorated_definition` wrapper, Java/C# annotations, Rust attributes each have a different shape), which no extractor here implements yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | | `doc_comment` | `String?` | `nil` | Documentation comment attached to the item, if any. The text of the comment (or run of comments) immediately preceding the item, with no blank line in between, when that comment is classified as a doc comment. Multiple adjacent single-line doc comments (Rust `///`) are joined with `\n` in source order. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`). `nil` for every other language, and for a preceding comment that is not in doc-comment form (a plain `#` comment in Python, Ruby, or Elixir) — Python’s docstring convention is captured separately, as `DocstringInfo`, not through this field. | | `signature` | `String?` | `nil` | Full signature text of the item (e.g., function parameters and return type). The item’s own source text from its start up to the start of its body (see `StructureItem.body_span`), trimmed of trailing whitespace — for example `fn add(a: i32, b: i32) -> i32` for a Rust function whose body is `{ a + b }`. `nil` only when that text is empty, which does not happen for any item `StructureKind` currently reports. Populated for every language and kind this library extracts structure for, since it is derived from `body_span`’s boundary rather than per-language syntax. | | `body_span` | `Span?` | `nil` | Source span covering only the body of the item, if distinct from the declaration. | *** #### SymbolInfo [Section titled “SymbolInfo”](#symbolinfo) A symbol (variable, function, type, etc.) extracted from source code. | Field | Type | Default | Description | | ----------------- | ------------ | ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `String` | — | The name of the symbol. | | `kind` | `SymbolKind` | `:variable` | The kind of symbol (variable, function, class, etc.). | | `span` | `Span` | — | Source span covering the symbol definition. | | `type_annotation` | `String?` | `nil` | Explicit type annotation, if present in the source. | | `doc` | `String?` | `nil` | Documentation comment immediately preceding this symbol, resolved by the same walk `StructureItem.doc_comment` uses (see `doc_comment_at`) — never hard-coded `nil`. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`) — the languages whose comment classification recognizes a doc-kind comment. `nil` for every other language (e.g. Python, Go, Ruby, which have no doc-kind comment classification), and also `nil` when a symbol in a supported language simply has no doc comment immediately above it. | *** #### Tree [Section titled “Tree”](#tree) A parsed syntax tree. Cheap to clone (refcount bump). ##### Methods [Section titled “Methods”](#methods-4) ###### root\_node() [Section titled “root\_node()”](#root_node) Return the root `Node` of this tree. **Signature:** ```ruby def root_node() ``` **Example:** ```ruby result = instance.root_node() ``` **Returns:** `Node` ###### walk() [Section titled “walk()”](#walk-1) Return a `TreeCursor` positioned at the root. **Signature:** ```ruby def walk() ``` **Example:** ```ruby result = instance.walk() ``` **Returns:** `TreeCursor` *** #### TreeCursor [Section titled “TreeCursor”](#treecursor) A cursor for traversing a `Tree`. ##### Methods [Section titled “Methods”](#methods-5) ###### node() [Section titled “node()”](#node-1) Return the `Node` at the cursor’s current position. **Signature:** ```ruby def node() ``` **Example:** ```ruby result = instance.node() ``` **Returns:** `Node` ###### goto\_first\_child() [Section titled “goto\_first\_child()”](#goto_first_child) Move the cursor to the first child of the current node. Returns `true` if a child existed. **Signature:** ```ruby def goto_first_child() ``` **Example:** ```ruby result = instance.goto_first_child() ``` **Returns:** `Boolean` ###### goto\_parent() [Section titled “goto\_parent()”](#goto_parent) Move the cursor to the parent of the current node. Returns `true` if a parent existed. **Signature:** ```ruby def goto_parent() ``` **Example:** ```ruby result = instance.goto_parent() ``` **Returns:** `Boolean` ###### goto\_next\_sibling() [Section titled “goto\_next\_sibling()”](#goto_next_sibling) Move the cursor to the next sibling of the current node. Returns `true` if a sibling existed. **Signature:** ```ruby def goto_next_sibling() ``` **Example:** ```ruby result = instance.goto_next_sibling() ``` **Returns:** `Boolean` ###### field\_name() [Section titled “field\_name()”](#field_name) Return the field name for the current node, if any. **Signature:** ```ruby def field_name() ``` **Example:** ```ruby result = instance.field_name() ``` **Returns:** `String?` *** ### Enums [Section titled “Enums”](#enums) #### DataNodeKind [Section titled “DataNodeKind”](#datanodekind) The kind of a data node extracted from a data-format file. Classifies each node in the hierarchical `DataNode` tree returned when `data_extraction` is enabled on `ProcessConfig`. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract) Unit variants serialize as a bare string (`"KeyValue"`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | -------------------------------------------------------------------------------------------------------------------- | | `key_value` | A key/value pair or mapping (json/toml/properties/yaml/hcl/cue/kdl pair, or a wrapper “object”/“mapping” container). | | `element` | An XML element with a tag name in `key` and attributes in `attributes`. | | `sequence` | A positional sequence item (JSON array element, YAML block sequence item, CSV/PSV row or cell). | *** #### StructureKind [Section titled “StructureKind”](#structurekind) The kind of structural item found in source code. Categorizes top-level and nested declarations such as functions, classes, structs, enums, traits, and more. Use `Other` for language-specific constructs that do not fit a standard category. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-1) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | ---------------------------------------------------------------------------------------------- | | `function` | A free-standing or associated function. | | `method` | A method defined inside a class, struct, trait, or impl block. | | `class` | A class definition. | | `struct` | A struct definition. | | `interface` | An interface or protocol definition. | | `enum` | An enum definition. | | `module` | A module or package declaration. | | `trait` | A trait definition. | | `impl` | An impl block (Rust) or similar implementation block. | | `namespace` | A namespace declaration. | | `other` | A language-specific construct that does not fit any standard category. — Fields: `0`: `String` | *** #### CommentKind [Section titled “CommentKind”](#commentkind) The kind of a comment found in source code. Distinguishes between single-line comments, block (multi-line) comments, and documentation comments. | Value | Description | | ------- | --------------------------------------------------------------------- | | `line` | A single-line comment (e.g., `// ...` or `# ...`). | | `block` | A block or multi-line comment using slash-star delimiters. | | `doc` | A documentation comment such as `/// ...` or slash-double-star block. | *** #### DocstringFormat [Section titled “DocstringFormat”](#docstringformat) The format of a docstring extracted from source code. Identifies the docstring convention used, which varies by language (e.g., Python triple-quoted strings, JSDoc, Rustdoc `///` comments). ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-2) Unit variants serialize as a bare string (`"JSDoc"`); the `Other` variant serializes as a single-keyed object (`{"Other": "rst"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | --------------------- | -------------------------------------------------------------------------------------------------- | | `python_triple_quote` | Python triple-quoted string docstring (`"""..."""`). | | `js_doc` | JavaScript/TypeScript JSDoc block comment (opens with two stars, closes with star-slash). | | `rustdoc` | Rust `///` or `//!` doc comment. | | `go_doc` | Go doc comment (a comment block immediately preceding a declaration). | | `java_doc` | Java Javadoc block comment (opens with two stars, closes with star-slash). | | `other` | A language-specific docstring format not covered by the standard variants. — Fields: `0`: `String` | *** #### ExportKind [Section titled “ExportKind”](#exportkind) The kind of an export statement found in source code. Covers named exports, default exports, and re-exports from other modules. | Value | Description | | ----------- | -------------------------------------------------------------------- | | `named` | A named export (e.g., `export { foo }`). | | `default` | A default export (e.g., `export default foo`). | | `re_export` | A re-export from another module (e.g., `export { foo } from 'bar'`). | *** #### SymbolKind [Section titled “SymbolKind”](#symbolkind) The kind of a symbol definition found in source code. Categorizes symbol definitions such as variables, constants, functions, classes, types, interfaces, enums, and modules. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-3) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | --------------------------------------------------------------------------- | | `variable` | A variable binding. | | `constant` | A constant (immutable binding). | | `function` | A function definition. | | `class` | A class definition. | | `type` | A type alias or typedef. | | `interface` | An interface definition. | | `enum` | An enum definition. | | `module` | A module declaration. | | `other` | A symbol kind not covered by the standard variants. — Fields: `0`: `String` | *** #### DiagnosticSeverity [Section titled “DiagnosticSeverity”](#diagnosticseverity) Severity level of a diagnostic produced during parsing. Used to classify parse errors, warnings, and informational messages found in the syntax tree. | Value | Description | | --------- | --------------------------------------------------------------- | | `error` | A parse error (e.g., an `ERROR` or `MISSING` node in the tree). | | `warning` | A warning-level diagnostic. | | `info` | An informational diagnostic. | *** ### Errors [Section titled “Errors”](#errors) #### Error [Section titled “Error”](#error) Errors that can occur when using the tree-sitter language pack. Covers language lookup failures, parse errors, query errors, and I/O issues. Feature-gated variants are included when `config`, `download`, or related features are enabled. ##### Matching on `Error` [Section titled “Matching on Error”](#matching-on-error) The set of variants is not stable: new failure modes are added in minor releases, and `Io`, `Json`, and `Toml` exist only under certain feature combinations, so the variant set a downstream crate sees depends on which features it enables. Downstream `match`es must therefore carry a `_` arm; `#[non_exhaustive]` makes the compiler enforce that instead of letting a feature change silently break a build. ##### C ABI error codes [Section titled “C ABI error codes”](#c-abi-error-codes) Each variant alef can see carries an explicit `alef(error_code = N)` allocation that becomes a member of the generated `AlefFfiErrorCode` C enum. These numbers are a public ABI contract: **an allocated number is never reused after its variant is removed**, and a variant’s number never changes, because C callers compare against the value, not the name. New variants take the next free number. 0-4 are reserved by alef, so allocation starts at 100. An unannotated variant is emitted as the unknown code rather than as itself, which silently flattens the taxonomy — annotate every new variant. | Variant | Description | | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language_not_found` | The requested language name (or alias) was not found in the registry. | | `dynamic_load` | A dynamic shared library could not be loaded at runtime. | | `null_language_pointer` | The tree-sitter language function returned a null pointer for the given language name. | | `parser_setup` | The language could not be applied to the parser (e.g., ABI version mismatch). | | `lock_poisoned` | An internal `RwLock` or `Mutex` was poisoned by a previous panic. | | `config` | A configuration file or value was invalid or could not be applied. | | `parse_failed` | The tree-sitter parser returned no tree for the given source input. | | `parse_timeout` | The parse was cancelled because it exceeded its configured wall-clock budget. Raised only when a budget is configured — see `ProcessConfig.parse_timeout_ms`, which defaults to `nil`. | | `query_error` | A tree-sitter query could not be compiled or executed. | | `invalid_range` | A byte range was invalid (e.g., end before start, or out of bounds). | | `download` | A parser download from GitHub releases failed. | | `checksum_mismatch` | The downloaded file’s SHA-256 digest did not match the manifest’s expected value. | | `cache_lock` | The cross-process download cache lock file could not be acquired or created. | *** # Rust API Reference ## Rust API Reference v1.16.1 [Section titled “Rust API Reference v1.16.1”](#rust-api-reference-v1161) ### Functions [Section titled “Functions”](#functions) #### detect\_language\_from\_extension() [Section titled “detect\_language\_from\_extension()”](#detect_language_from_extension) Detect language name from a file extension (without leading dot). Returns `None` for unrecognized extensions. The match is case-insensitive. **Signature:** ```rust pub fn detect_language_from_extension(ext: &str) -> Option ``` **Example:** ```rust let result = detect_language_from_extension("value"); ``` **Parameters:** | Name | Type | Required | Description | | ----- | ------ | -------- | ----------- | | `ext` | `&str` | Yes | The ext | **Returns:** `Option` *** #### detect\_language\_from\_path() [Section titled “detect\_language\_from\_path()”](#detect_language_from_path) Detect language name from a file path. Extracts the file extension and looks it up. Returns `None` if the path has no extension or the extension is not recognized. **Signature:** ```rust pub fn detect_language_from_path(path: &str) -> Option ``` **Example:** ```rust let result = detect_language_from_path("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------ | -------- | ---------------- | | `path` | `&str` | Yes | Path to the file | **Returns:** `Option` *** #### detect\_language\_from\_content() [Section titled “detect\_language\_from\_content()”](#detect_language_from_content) Detect language name from file content using the shebang line (`#!`). Inspects only the first line of `content`. If it begins with `#!`, the interpreter name is extracted and mapped to a language name. Handles common patterns: * `#!/usr/bin/env python3` → `"python"` * `#!/bin/bash` → `"bash"` * `#!/usr/bin/env node` → `"javascript"` The `-S` flag accepted by some `env` implementations is skipped automatically. Version suffixes (e.g. `python3.11`, `ruby3.2`) are stripped before matching. A leading UTF-8 BOM (`U+FEFF`) is skipped before the `#!` check, so a BOM-prefixed script is still detected by its shebang. Returns `None` when content does not start with `#!` (after stripping a leading BOM), the shebang is malformed, or the interpreter is not recognised. **Signature:** ```rust pub fn detect_language_from_content(content: &str) -> Option ``` **Example:** ```rust let result = detect_language_from_content("value"); ``` **Parameters:** | Name | Type | Required | Description | | --------- | ------ | -------- | ---------------------- | | `content` | `&str` | Yes | The content to process | **Returns:** `Option` *** #### get\_highlights\_query() [Section titled “get\_highlights\_query()”](#get_highlights_query) Get the highlights query for a language, if bundled. Returns the contents of `highlights.scm` as a static string, or `None` if no highlights query is bundled for this language. **Signature:** ```rust pub fn get_highlights_query(language: &str) -> Option ``` **Example:** ```rust use tree_sitter_language_pack::get_highlights_query; // Returns Some(...) for languages with bundled queries let query = get_highlights_query("python"); // Returns None for languages without bundled highlights queries let missing = get_highlights_query("nonexistent_lang"); assert!(missing.is_none()); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------ | -------- | ------------ | | `language` | `&str` | Yes | The language | **Returns:** `Option` *** #### get\_injections\_query() [Section titled “get\_injections\_query()”](#get_injections_query) Get the injections query for a language, if bundled. Returns the contents of `injections.scm` as a static string, or `None` if no injections query is bundled for this language. **Signature:** ```rust pub fn get_injections_query(language: &str) -> Option ``` **Example:** ```rust use tree_sitter_language_pack::get_injections_query; let query = get_injections_query("markdown"); // Returns None for languages without bundled injections queries let missing = get_injections_query("nonexistent_lang"); assert!(missing.is_none()); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------ | -------- | ------------ | | `language` | `&str` | Yes | The language | **Returns:** `Option` *** #### get\_locals\_query() [Section titled “get\_locals\_query()”](#get_locals_query) Get the locals query for a language, if bundled. Returns the contents of `locals.scm` as a static string, or `None` if no locals query is bundled for this language. **Signature:** ```rust pub fn get_locals_query(language: &str) -> Option ``` **Example:** ```rust use tree_sitter_language_pack::get_locals_query; let query = get_locals_query("python"); // Returns None for languages without bundled locals queries let missing = get_locals_query("nonexistent_lang"); assert!(missing.is_none()); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------ | -------- | ------------ | | `language` | `&str` | Yes | The language | **Returns:** `Option` *** #### get\_tags\_query() [Section titled “get\_tags\_query()”](#get_tags_query) Get the tags query for a language, if bundled. Returns the contents of `tags.scm` as a static string, or `None` if no tags query is bundled for this language. **Signature:** ```rust pub fn get_tags_query(language: &str) -> Option ``` **Example:** ```rust use tree_sitter_language_pack::get_tags_query; let query = get_tags_query("rust"); // Returns None for languages without bundled tags queries let missing = get_tags_query("nonexistent_lang"); assert!(missing.is_none()); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------ | -------- | ------------ | | `language` | `&str` | Yes | The language | **Returns:** `Option` *** #### get\_indents\_query() [Section titled “get\_indents\_query()”](#get_indents_query) Get the indents query for a language, if bundled. Returns the contents of `indents.scm` (used for auto-indentation) as a static string, or `None` if no indents query is bundled for this language. **Signature:** ```rust pub fn get_indents_query(language: &str) -> Option ``` **Example:** ```rust use tree_sitter_language_pack::get_indents_query; let query = get_indents_query("objc"); // Returns None for languages without bundled indents queries let missing = get_indents_query("nonexistent_lang"); assert!(missing.is_none()); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------ | -------- | ------------ | | `language` | `&str` | Yes | The language | **Returns:** `Option` *** #### get\_folds\_query() [Section titled “get\_folds\_query()”](#get_folds_query) Get the folds query for a language, if bundled. Returns the contents of `folds.scm` (used for code folding) as a static string, or `None` if no folds query is bundled for this language. **Signature:** ```rust pub fn get_folds_query(language: &str) -> Option ``` **Example:** ```rust use tree_sitter_language_pack::get_folds_query; let query = get_folds_query("rust"); // Returns None for languages without bundled folds queries let missing = get_folds_query("nonexistent_lang"); assert!(missing.is_none()); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------ | -------- | ------------ | | `language` | `&str` | Yes | The language | **Returns:** `Option` *** #### get\_language() [Section titled “get\_language()”](#get_language) Get a tree-sitter `Language` by name using the global registry. Resolves language aliases (e.g., `"shell"` maps to `"bash"`). When the `download` feature is enabled (default), automatically downloads the parser from GitHub releases if not found locally. **Errors:** Returns `Error::LanguageNotFound` if the language is not recognized, or `Error::Download` if auto-download fails. **Signature:** ```rust pub fn get_language(name: &str) -> Result ``` **Example:** ```rust use tree_sitter_language_pack::{get_language, Parser}; let _lang = get_language("python")?; let mut parser = Parser::new(); parser.set_language("python")?; let tree = parser.parse("x = 1").expect("parse failed"); assert_eq!(tree.root_node().kind(), "module"); # Ok::<(), tree_sitter_language_pack::Error>(()) ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------ | -------- | ----------- | | `name` | `&str` | Yes | The name | **Returns:** `Language` **Errors:** Returns `Err(Error)`. *** #### get\_parser() [Section titled “get\_parser()”](#get_parser) Get a `Parser` pre-configured for the given language. This is a convenience function that calls `get_language` and configures a new parser in one step. **Errors:** Returns `Error::LanguageNotFound` if the language is not recognized, or `Error::ParserSetup` if the language cannot be applied to the parser. **Signature:** ```rust pub fn get_parser(name: &str) -> Result ``` **Example:** ```rust use tree_sitter_language_pack::get_parser; let mut parser = get_parser("rust")?; let tree = parser.parse("fn main() {}").expect("parse failed"); assert!(!tree.root_node().has_error()); # Ok::<(), tree_sitter_language_pack::Error>(()) ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------ | -------- | ----------- | | `name` | `&str` | Yes | The name | **Returns:** `Parser` **Errors:** Returns `Err(Error)`. *** #### detect\_language() [Section titled “detect\_language()”](#detect_language) Detect language name from a file path or extension. This compatibility alias matches the pre-Alef Python binding API. **Signature:** ```rust pub fn detect_language(path: &str) -> Option ``` **Example:** ```rust let result = detect_language("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------ | -------- | ---------------- | | `path` | `&str` | Yes | Path to the file | **Returns:** `Option` *** #### available\_languages() [Section titled “available\_languages()”](#available_languages) List all available language names (sorted, deduplicated, includes aliases). Returns names of both statically compiled and dynamically loadable languages, plus any configured aliases. **Signature:** ```rust pub fn available_languages() -> Vec ``` **Example:** ```rust use tree_sitter_language_pack::available_languages; let langs = available_languages(); for name in &langs { println!("{}", name); } ``` **Returns:** `Vec` *** #### has\_language() [Section titled “has\_language()”](#has_language) Check if a language is available by name or alias. Returns `true` if the language can be loaded (statically compiled, dynamically available, or a known alias for one of these). **Signature:** ```rust pub fn has_language(name: &str) -> bool ``` **Example:** ```rust use tree_sitter_language_pack::has_language; assert!(has_language("python")); assert!(has_language("shell")); // alias for "bash" assert!(!has_language("nonexistent_language")); ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------ | -------- | ----------- | | `name` | `&str` | Yes | The name | **Returns:** `bool` *** #### language\_count() [Section titled “language\_count()”](#language_count) Return the number of available languages. Includes statically compiled languages, dynamically loadable languages, and aliases. **Signature:** ```rust pub fn language_count() -> usize ``` **Example:** ```rust use tree_sitter_language_pack::language_count; let count = language_count(); println!("{} languages available", count); ``` **Returns:** `usize` *** #### process() [Section titled “process()”](#process) Process source code and extract file intelligence using the global registry. Parses the source with tree-sitter and extracts metrics, structure, imports, exports, comments, docstrings, symbols, diagnostics, and/or chunks based on the flags set in `ProcessConfig`. **Errors:** Returns `Error::InvalidRange` if the config carries a zero-valued limit or the source exceeds `ProcessConfig::max_source_bytes`, `Error::ParseTimeout` if the parse exceeds `ProcessConfig::parse_timeout_ms`, `Error::LanguageNotFound` if the language is unknown, or `Error::ParseFailed` if parsing yields no tree. **Signature:** ```rust pub fn process(source: &str, config: &ProcessConfig) -> Result ``` **Example:** ```rust use tree_sitter_language_pack::{ProcessConfig, process}; let config = ProcessConfig::new("python").all(); let result = process("def hello(): pass", &config).unwrap(); println!("Language: {}", result.language); println!("Lines: {}", result.metrics.total_lines); println!("Structures: {}", result.structure.len()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ---------------- | -------- | ------------------------- | | `source` | `&str` | Yes | The source | | `config` | `&ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Returns `Err(Error)`. *** #### init() [Section titled “init()”](#init) Initialize the language pack with the given configuration. Applies any custom cache directory, then downloads all languages and groups specified in the config. This is the recommended entry point when you want to pre-warm the cache before use. **Errors:** Returns an error if configuration cannot be applied or if downloads fail. **Signature:** ```rust pub fn init(config: &PackConfig) -> Result<(), Error> ``` **Example:** ```rust use tree_sitter_language_pack::{PackConfig, init}; let config = PackConfig { cache_dir: None, languages: Some(vec!["python".to_string(), "rust".to_string()]), groups: None, }; init(&config).unwrap(); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------- | -------- | ------------------------- | | `config` | `&PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Returns `Err(Error)`. *** #### configure() [Section titled “configure()”](#configure) Apply download configuration without downloading anything. Use this to set a custom cache directory before the first call to `get_language` or any download function. Changing the cache dir after languages have been registered has no effect on already-loaded languages. `PackConfig::cache_dir` is a BASE directory, not the final libs path: this crate appends `tree-sitter-language-pack/v{version}/libs` to it, the same suffix applied to the platform default cache directory. In the example below, files actually land under `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`, never directly in `/tmp/my-parsers/`. Call `cache_dir` to read back the resolved, fully-suffixed path. **Errors:** Returns an error if the lock cannot be acquired. **Signature:** ```rust pub fn configure(config: &PackConfig) -> Result<(), Error> ``` **Example:** ```rust use std::path::PathBuf; use tree_sitter_language_pack::{PackConfig, configure}; let config = PackConfig { cache_dir: Some(PathBuf::from("/tmp/my-parsers")), languages: None, groups: None, }; configure(&config).unwrap(); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------- | -------- | ------------------------- | | `config` | `&PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Returns `Err(Error)`. *** #### download() [Section titled “download()”](#download) Download specific languages to the local cache. Returns the number of distinct languages available after the call. Already compiled or cached languages are included in the count. Aliases are resolved before counting, so `["shell", "bash"]` names one language and returns 1. **Errors:** Returns an error if any language is not available in the manifest or if the download fails. **Signature:** ```rust pub fn download(names: &[&str]) -> Result ``` **Example:** ```rust use tree_sitter_language_pack::download; let count = download(&["python", "rust", "typescript"]).unwrap(); println!("Ensured {} languages", count); ``` **Parameters:** | Name | Type | Required | Description | | ------- | ----------- | -------- | ----------- | | `names` | `&\[&str\]` | Yes | The names | **Returns:** `usize` **Errors:** Returns `Err(Error)`. *** #### prefetch() [Section titled “prefetch()”](#prefetch) Prefetch grammars: download any not already loadable from disk, then load every requested language into the process registry so a subsequent hot loop only parses. Unlike `download()`, this does not trust in-memory availability — it downloads whenever a grammar is not actually loadable from disk (fixing the case where a known-but-not-downloaded grammar is reported present), then resolves and caches every requested language. Call it once, up front, before a parallel workload. **Errors:** Returns `Error::Download` if a required grammar cannot be fetched, or `Error::LanguageNotFound` if a requested name is unknown. **Signature:** ```rust pub fn prefetch(languages: &[&str]) -> Result<(), Error> ``` **Example:** ```rust use tree_sitter_language_pack::prefetch; prefetch(&["rust", "python", "go"])?; # Ok::<(), tree_sitter_language_pack::Error>(()) ``` **Parameters:** | Name | Type | Required | Description | | ----------- | ----------- | -------- | ------------- | | `languages` | `&\[&str\]` | Yes | The languages | **Returns:** No return value. **Errors:** Returns `Err(Error)`. *** #### download\_all() [Section titled “download\_all()”](#download_all) Download all available languages from the remote manifest. Downloads the platform bundle and extracts every library it contains. Languages that appear in the manifest but are absent from the bundle (e.g. grammars that failed to compile at release time) are silently skipped — they are not treated as an error. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns an error if the manifest cannot be fetched or the bundle download fails. **Signature:** ```rust pub fn download_all() -> Result ``` **Example:** ```rust use tree_sitter_language_pack::download_all; let count = download_all().unwrap(); println!("{} languages available", count); ``` **Returns:** `usize` **Errors:** Returns `Err(Error)`. *** #### download\_group() [Section titled “download\_group()”](#download_group) Download every language in a named group. Groups are defined by the remote manifest, not by this library, and let you ensure a curated set of related grammars in one call instead of listing each name to `download()`. Already-cached languages are skipped. Call `manifest_groups` to discover the group names the manifest actually defines. The published manifest currently defines a single group, `"all"`; earlier revisions of this documentation advertised `"web"`, `"data"`, and `"systems"`, which the manifest has never contained, so every call following that example failed. Do not hardcode a group name without checking. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns `Error::Download` if the manifest cannot be fetched, if the group is unknown — the message lists the groups the manifest defines — or if any constituent language fails to download. **Signature:** ```rust pub fn download_group(name: &str) -> Result ``` **Example:** ```rust use tree_sitter_language_pack::{download_group, manifest_groups}; let group = manifest_groups()?.into_iter().next().expect("manifest defines no groups"); let count = download_group(&group)?; println!("{count} languages available"); # Ok::<(), tree_sitter_language_pack::Error>(()) ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------ | -------- | ----------- | | `name` | `&str` | Yes | The name | **Returns:** `usize` **Errors:** Returns `Err(Error)`. *** #### manifest\_languages() [Section titled “manifest\_languages()”](#manifest_languages) Return all language names available in the remote manifest (371). Fetches (and caches) the remote manifest to discover the full list of downloadable languages. Use `downloaded_languages` to list what is already cached locally. **Errors:** Returns an error if the manifest cannot be fetched. **Signature:** ```rust pub fn manifest_languages() -> Result, Error> ``` **Example:** ```rust use tree_sitter_language_pack::manifest_languages; let langs = manifest_languages().unwrap(); println!("{} languages available for download", langs.len()); ``` **Returns:** `Vec` **Errors:** Returns `Err(Error)`. *** #### manifest\_groups() [Section titled “manifest\_groups()”](#manifest_groups) Return the names of every language group the remote manifest defines, sorted. Group names are manifest data, not a compile-time constant of this library, so this is the only reliable way to learn what `download_group` and `PackConfig::groups` accept. The published manifest currently defines just `"all"`. **Errors:** Returns `Error::Download` if the manifest cannot be fetched. **Signature:** ```rust pub fn manifest_groups() -> Result, Error> ``` **Example:** ```rust use tree_sitter_language_pack::manifest_groups; for group in manifest_groups()? { println!("{group}"); } # Ok::<(), tree_sitter_language_pack::Error>(()) ``` **Returns:** `Vec` **Errors:** Returns `Err(Error)`. *** #### downloaded\_languages() [Section titled “downloaded\_languages()”](#downloaded_languages) Return languages that are already downloaded and cached locally. Does not perform any network requests. Returns an empty list if the cache directory does not exist or cannot be read. **Signature:** ```rust pub fn downloaded_languages() -> Vec ``` **Example:** ```rust use tree_sitter_language_pack::downloaded_languages; let langs = downloaded_languages(); println!("{} languages already cached", langs.len()); ``` **Returns:** `Vec` *** #### clean\_cache() [Section titled “clean\_cache()”](#clean_cache) Delete all cached parser shared libraries. Resets the cache registration so the next call to `get_language` or a download function will re-register the (now empty) cache directory. **Errors:** Returns an error if the cache directory cannot be removed. **Signature:** ```rust pub fn clean_cache() -> Result<(), Error> ``` **Example:** ```rust use tree_sitter_language_pack::clean_cache; clean_cache().unwrap(); println!("Cache cleared"); ``` **Returns:** No return value. **Errors:** Returns `Err(Error)`. *** #### cache\_dir() [Section titled “cache\_dir()”](#cache_dir) Return the effective cache directory path. This is `{base}/tree-sitter-language-pack/v{version}/libs/`, where `{base}` is either the custom BASE directory set via `configure` / `init` (`PackConfig::cache_dir`) or the platform default cache directory — both are suffixed identically, so a custom `cache_dir` is never used as the final libs path. The default resolves to `~/.cache/tree-sitter-language-pack/v{version}/libs/` on a typical Unix system. **Errors:** Returns an error if no cache directory can be resolved: `version` is somehow invalid, or (with no custom `cache_dir` configured) the platform reports none and `TREE_SITTER_LANGUAGE_PACK_CACHE_DIR` is unset. This crate no longer falls back to the temporary directory for the latter case — see #101 H2. **Signature:** ```rust pub fn cache_dir() -> Result ``` **Example:** ```rust use tree_sitter_language_pack::cache_dir; let dir = cache_dir().unwrap(); println!("Cache directory: {dir}"); ``` **Returns:** `String` **Errors:** Returns `Err(Error)`. *** ### Types [Section titled “Types”](#types) #### ByteRange [Section titled “ByteRange”](#byterange) A byte range — start (inclusive) to end (exclusive). | Field | Type | Default | Description | | ------- | ------- | ------- | ---------------------------- | | `start` | `usize` | — | Inclusive start byte offset. | | `end` | `usize` | — | Exclusive end byte offset. | *** #### ChunkContext [Section titled “ChunkContext”](#chunkcontext) Metadata for a single chunk of source code. | Field | Type | Default | Description | | ----------------- | -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `language` | `String` | — | Language name used to parse this chunk. | | `chunk_index` | `usize` | — | Zero-indexed position of this chunk within the file’s chunk list. | | `total_chunks` | `usize` | — | Total number of chunks the file was split into. | | `node_types` | `Vec` | `vec![]` | Tree-sitter node kinds that appear at the top level of this chunk. | | `context_path` | `Vec` | `vec![]` | Hierarchical path of enclosing structural items (e.g., `["MyClass", "my_method"]`). | | `symbols_defined` | `Vec` | `vec![]` | Names of symbols defined within this chunk. | | `comments` | `Vec` | `vec![]` | Comments contained within this chunk. | | `docstrings` | `Vec` | `vec![]` | Docstrings contained within this chunk. Populated only for Python — the same language for which `ProcessResult::docstrings` is populated, and by the same classifier. Always empty for every other language. | | `has_error_nodes` | `bool` | — | Whether this chunk contains any tree-sitter error nodes. | *** #### CodeChunk [Section titled “CodeChunk”](#codechunk) A chunk of source code with rich metadata. | Field | Type | Default | Description | | ------------ | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `content` | `String` | — | The raw source text of this chunk. | | `start_byte` | `usize` | — | Inclusive start byte offset of this chunk in the original source. | | `end_byte` | `usize` | — | Exclusive end byte offset of this chunk in the original source. | | `start_line` | `usize` | — | Zero-indexed start line of this chunk. | | `end_line` | `usize` | — | Zero-indexed row of the last byte actually included in this chunk (inclusive — the same row a `Span::end_line` would report for a node ending on that byte). Computed the same way regardless of whether the source has a trailing newline: it is always the row of `end_byte - 1`, never a phantom row past the file’s real content. | | `metadata` | `ChunkContext` | — | Contextual metadata about this chunk. | *** #### CommentInfo [Section titled “CommentInfo”](#commentinfo) A comment extracted from source code. | Field | Type | Default | Description | | ----------------- | ---------------- | -------------------- | ----------------------------------------------------------------- | | `text` | `String` | — | The raw text content of the comment. | | `kind` | `CommentKind` | `CommentKind::Line` | The kind of comment (line, block, or doc). | | `span` | `Span` | — | Source span covering the comment. | | `associated_node` | `Option` | `Default::default()` | Name of the syntax node this comment is directly associated with. | *** #### DataAttribute [Section titled “DataAttribute”](#dataattribute) An XML-style attribute attached to an `Element` node. Populated only for `DataNodeKind::Element`; always empty for `KeyValue` and `Sequence` nodes. | Field | Type | Default | Description | | ------- | -------- | ------- | --------------------------------------------------------------- | | `name` | `String` | — | Attribute name (e.g. `"class"`, `"href"`). | | `value` | `String` | — | Attribute value as a raw string (quotes stripped). | | `span` | `Span` | — | Source span covering the entire `name="value"` attribute token. | *** #### DataNode [Section titled “DataNode”](#datanode) A node in the hierarchical data tree produced by data-format extraction. When `ProcessConfig::data_extraction` is `true`, `ProcessResult::data` is populated with a root `DataNode` whose `children` mirror the structure of the parsed file. The `kind` field determines which other fields are meaningful: | `kind` | `key` | `value` | `attributes` | `children` | | ---------- | ------------------------- | ------------ | ------------ | -------------- | | `KeyValue` | key / mapping key / index | leaf value | empty | nested map | | `Element` | XML tag name | text content | XML attrs | child elements | | `Sequence` | positional index (`"0"`) | leaf value | empty | sub-items | | Field | Type | Default | Description | | ------------ | -------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------- | | `kind` | `DataNodeKind` | `DataNodeKind::KeyValue` | Whether this node is a key/value pair, XML element, or sequence item. | | `key` | `Option` | `Default::default()` | Key, attribute name, tag name, or positional index (`"0"`, `"1"`, …). `None` at the document root. | | `value` | `Option` | `Default::default()` | Leaf scalar value, if any. `None` for containers (objects, arrays, XML elements with child elements). | | `attributes` | `Vec` | `vec![]` | Attributes on element-shape nodes (XML `STag` attributes). Empty for all other kinds. | | `children` | `Vec` | `vec![]` | Children for nested containers and XML element bodies. | | `span` | `Span` | — | Source span covering this node in the original source file. | *** #### Diagnostic [Section titled “Diagnostic”](#diagnostic) A diagnostic (syntax error, missing node, etc.) from parsing. | Field | Type | Default | Description | | ---------- | -------------------- | --------------------------- | ---------------------------------------------- | | `message` | `String` | — | Human-readable description of the diagnostic. | | `severity` | `DiagnosticSeverity` | `DiagnosticSeverity::Error` | Severity of the diagnostic. | | `span` | `Span` | — | Source span where the diagnostic was detected. | *** #### DocSection [Section titled “DocSection”](#docsection) A section within a docstring (e.g., Args, Returns, Raises). | Field | Type | Default | Description | | ------------- | ---------------- | -------------------- | ------------------------------------------------------- | | `kind` | `String` | — | Section kind (e.g., `"args"`, `"returns"`, `"raises"`). | | `name` | `Option` | `Default::default()` | Parameter or return value name, if applicable. | | `description` | `String` | — | Description text for this section. | *** #### DocstringInfo [Section titled “DocstringInfo”](#docstringinfo) A docstring extracted from source code. | Field | Type | Default | Description | | ----------------- | ----------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | `String` | — | The raw text of the docstring. | | `format` | `DocstringFormat` | `DocstringFormat::PythonTripleQuote` | The docstring format (Python, JSDoc, Rustdoc, etc.). | | `span` | `Span` | — | Source span covering the docstring. | | `associated_item` | `Option` | `Default::default()` | Name of the item this docstring documents. | | `parsed_sections` | `Vec` | `vec![]` | Parsed sections of the docstring (Args, Returns, Raises, etc.). **Reserved: not yet populated.** Always empty, for every `DocstringFormat`. Parsing a docstring body into sections requires implementing each convention’s own layout (Google/NumPy/reST style for Python, `@param`/`@returns` for JSDoc/Javadoc, and so on), which no extractor here does yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | *** #### DownloadManager [Section titled “DownloadManager”](#downloadmanager) Manages downloading and caching of pre-built parser shared libraries. ##### Methods [Section titled “Methods”](#methods) ###### new() [Section titled “new()”](#new) Create a new download manager for the given version. **Errors:** Returns `Error::Download` if `version` is empty, contains a path separator or `..`, or contains a character outside `[A-Za-z0-9.+-]` — see `validate_version` — or if no cache directory can be resolved (see `Self::default_cache_dir`). **Signature:** ```rust pub fn new(version: &str) -> Result ``` **Example:** ```rust let result = DownloadManager::new("value")?; ``` **Parameters:** | Name | Type | Required | Description | | --------- | ------ | -------- | ----------- | | `version` | `&str` | Yes | The version | **Returns:** `DownloadManager` **Errors:** Returns `Err(Error)`. ###### installed\_languages() [Section titled “installed\_languages()”](#installed_languages) List languages that are already downloaded and cached. Derived from the on-disk cache filenames, one canonical name per file, plus every alias that resolves to it (via `aliases_for`) — so this list agrees with the user-facing `LanguageRegistry::available_languages` about which names are “available”; both report `"shell"` once `bash` is cached, for example. A previous version reported canonical names only, which could never agree with `available_languages()`. See #107. Returns an empty list if the cache directory does not exist. If it exists but cannot be read (e.g. a permission error), also returns an empty list — changing this to a `Result` would be a breaking change across every language binding — but logs a `tracing::warn!` so the failure is not silently indistinguishable from “nothing installed”. **Signature:** ```rust pub fn installed_languages(&self) -> Vec ``` **Example:** ```rust let result = instance.installed_languages(); ``` **Returns:** `Vec` ###### download\_all\_best\_effort() [Section titled “download\_all\_best\_effort()”](#download_all_best_effort) Download the platform bundle and extract every library file it contains. Unlike `Self::ensure_languages`, this does not check the manifest language list against archive contents — it simply extracts all `.so`/`.dylib`/`.dll` files from the bundle. Languages in the manifest that are missing from the archive are silently ignored rather than returning an error. Returns the number of library files extracted (including those already cached). **Signature:** ```rust pub fn download_all_best_effort(&self) -> Result ``` **Example:** ```rust let result = instance.download_all_best_effort()?; ``` **Returns:** `usize` **Errors:** Returns `Err(Error)`. ###### clean\_cache() [Section titled “clean\_cache()”](#clean_cache-1) Remove all cached parser libraries. Acquires the cross-process lock so `clean_cache` cannot race a concurrent downloader (avoids Windows sharing-violation errors against an in-flight bundle write). The `.download.lock` file itself is **not** removed — it is permanent infrastructure; deleting it could allow a concurrent process that already opened the file to continue holding a stale lock handle while a new process opens a fresh inode, breaking the mutual-exclusion guarantee. **Signature:** ```rust pub fn clean_cache(&self) -> Result<(), Error> ``` **Example:** ```rust instance.clean_cache()?; ``` **Returns:** No return value. **Errors:** Returns `Err(Error)`. *** #### ExportInfo [Section titled “ExportInfo”](#exportinfo) An export statement extracted from source code. | Field | Type | Default | Description | | ------ | ------------ | ------------------- | -------------------------------------------------- | | `name` | `String` | — | The exported name. | | `kind` | `ExportKind` | `ExportKind::Named` | The kind of export (named, default, or re-export). | | `span` | `Span` | — | Source span covering the export statement. | *** #### FileMetrics [Section titled “FileMetrics”](#filemetrics) Aggregate metrics for a source file. | Field | Type | Default | Description | | --------------- | ------- | ------- | -------------------------------------------------------------- | | `total_lines` | `usize` | — | Total number of lines (including blank and comment lines). | | `code_lines` | `usize` | — | Number of lines containing non-blank, non-comment source code. | | `comment_lines` | `usize` | — | Number of lines that are entirely comments. | | `blank_lines` | `usize` | — | Number of blank (whitespace-only) lines. | | `total_bytes` | `usize` | — | Total byte length of the source file. | | `node_count` | `usize` | — | Total number of nodes in the syntax tree. | | `error_count` | `usize` | — | Number of error nodes in the syntax tree (parse errors). | | `max_depth` | `usize` | — | Maximum nesting depth reached in the syntax tree. | *** #### ImportInfo [Section titled “ImportInfo”](#importinfo) An import statement extracted from source code. | Field | Type | Default | Description | | ------------- | ---------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `source` | `String` | — | The module or path being imported from. | | `items` | `Vec` | `vec![]` | Specific names imported from the source module. For `import a, b` / `from m import a, b`, every entry’s base name (never the alias). For a JavaScript/TypeScript named-imports clause (`import { a, b as c } from 'm'`), every specifier’s original name. Populated for Python and JavaScript/TypeScript only. Always empty for every other language this library recognises import statements for — Rust, Go, Java, Kotlin, and Elixir (`import`/`alias`/`require`/`use`) — and for a JS/TS namespace import (`import * as ns`) or default import (`import x from 'm'`), neither of which names individual items. | | `alias` | `Option` | `Default::default()` | Alias assigned to the import (e.g., `import numpy as np`). Populated for Python’s single-name form (`import numpy as np`, `from m import a as b`) and JavaScript/TypeScript’s namespace form (`import * as ns from 'm'`) or a named-imports clause naming exactly one specifier (`import { a as b } from 'm'`). `None` for Rust, Go, Java, Kotlin, and Elixir (which has its own `as:` alias option on `alias` directives, not yet extracted here) — and for a Python statement that aliases several names at once (`import os, sys as s`), where there is no single alias to report for the statement as a whole, so only `items` is populated for it. | | `is_wildcard` | `bool` | — | Whether this is a wildcard import (e.g., `import *` or `use foo::*`). Detected from the syntax tree — a dedicated wildcard node (`wildcard_import` in Python, `use_wildcard` in Rust) or a bare `*` token outside of string-literal content — not by searching the import’s source text for a `*` character, so a glob in an import path string (`import a from './glob*.js'`) is not mistaken for one. | | `span` | `Span` | — | Source span covering the import statement. | *** #### Language [Section titled “Language”](#language) *** #### LanguageRegistry [Section titled “LanguageRegistry”](#languageregistry) Thread-safe registry of tree-sitter language parsers. Manages both statically compiled and dynamically loaded language grammars. Use `LanguageRegistry::new()` for the default registry, or access the global instance via the module-level convenience functions (`get_language`, `available_languages`, etc.). ##### Methods [Section titled “Methods”](#methods-1) ###### new() [Section titled “new()”](#new-1) Create a new registry populated with all statically compiled languages. When the `dynamic-loading` feature is enabled, the registry also knows about dynamically loadable grammars and will load them on demand. **Signature:** ```rust pub fn new() -> LanguageRegistry ``` **Example:** ```rust let result = LanguageRegistry::new(); ``` **Returns:** `LanguageRegistry` ###### get\_language() [Section titled “get\_language()”](#get_language-1) Get a tree-sitter `Language` by name. Resolves aliases (e.g., `"shell"` -> `"bash"`, `"makefile"` -> `"make"`), then looks up the language in the static table. When the `dynamic-loading` feature is enabled, falls back to loading a shared library on demand. **Errors:** Returns `Error::LanguageNotFound` if the name (after alias resolution) does not match any known grammar. **Signature:** ```rust pub fn get_language(&self, name: &str) -> Result ``` **Example:** ```rust let result = instance.get_language("value")?; ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------ | -------- | ----------- | | `name` | `&str` | Yes | The name | **Returns:** `Language` **Errors:** Returns `Err(Error)`. ###### available\_languages() [Section titled “available\_languages()”](#available_languages-1) List all available language names, sorted and deduplicated. Includes statically compiled languages, dynamically loadable languages (if the `dynamic-loading` feature is enabled), and all configured aliases. **Signature:** ```rust pub fn available_languages(&self) -> Vec ``` **Example:** ```rust let result = instance.available_languages(); ``` **Returns:** `Vec` ###### has\_parser() [Section titled “has\_parser()”](#has_parser) Check whether this language can be parsed right now, without downloading. Resolves aliases, then answers from exactly the lookup `get_language` performs: the statically compiled table, the already-loaded dynamic grammars, and the parser shared libraries present in the primary and extra (download-cache) library directories. It never performs network I/O. A previous implementation consulted only the statically compiled table. That table is empty in every build that does not set `TSLP_LANGUAGES`, so the function answered `false` for languages this registry parses perfectly well. Contrast `has_language`, which is also `true` for a grammar that is merely *known to the manifest* and would have to be downloaded first. The pair distinguishes “we can parse it offline, now” from “we recognise the name”. The first `true` answer for a dynamic grammar loads its shared library: loading is the only way to know the grammar is usable, since a truncated or wrong-architecture library exists on disk but cannot parse. Loads are cached process-wide, so repeat calls are cheap. **Signature:** ```rust pub fn has_parser(&self, name: &str) -> bool ``` **Example:** ```rust let result = instance.has_parser("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------ | -------- | ----------- | | `name` | `&str` | Yes | The name | **Returns:** `bool` ###### has\_language() [Section titled “has\_language()”](#has_language-1) Check whether a language is available by name or alias. Returns `true` if the language can be loaded, either from the static table or from a dynamic library on disk. Every branch is one more way to answer `true`, so they are ordered cheapest-first and the filesystem is only consulted once every in-memory source has said no. Probing the loaded-grammar map and the manifest ahead of the `stat` calls is what keeps this off the syscall path for the languages a process actually uses. **Signature:** ```rust pub fn has_language(&self, name: &str) -> bool ``` **Example:** ```rust let result = instance.has_language("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------ | -------- | ----------- | | `name` | `&str` | Yes | The name | **Returns:** `bool` ###### language\_count() [Section titled “language\_count()”](#language_count-1) Return the total number of available languages (including aliases). Counts the same set `available_languages` lists, without materialising or sorting it. **Signature:** ```rust pub fn language_count(&self) -> usize ``` **Example:** ```rust let result = instance.language_count(); ``` **Returns:** `usize` ###### process() [Section titled “process()”](#process-1) Parse source code and extract file intelligence based on config in a single pass. **Errors:** Returns `Error::InvalidRange` if the config is invalid (see `ProcessConfig::validate`) or if the source exceeds the configured `max_source_bytes`; `Error::LanguageNotFound` if the language is unknown; or `Error::ParseFailed` if parsing produces no tree. **Signature:** ```rust pub fn process(&self, source: &str, config: &ProcessConfig) -> Result ``` **Example:** ```rust let result = instance.process("value", &ProcessConfig::default())?; ``` **Parameters:** | Name | Type | Required | Description | | -------- | ---------------- | -------- | ------------------------- | | `source` | `&str` | Yes | The source | | `config` | `&ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Returns `Err(Error)`. ###### default() [Section titled “default()”](#default) **Signature:** ```rust pub fn default() -> LanguageRegistry ``` **Example:** ```rust let result = LanguageRegistry::default(); ``` **Returns:** `LanguageRegistry` *** #### Node [Section titled “Node”](#node) A single syntax node within a `Tree`. Nodes hold a strong reference to their parent tree so they remain valid regardless of how the tree is moved or stored at the FFI boundary. ##### Methods [Section titled “Methods”](#methods-2) ###### kind() [Section titled “kind()”](#kind) Return the node’s kind name (e.g. `"function_definition"`). **Signature:** ```rust pub fn kind(&self) -> String ``` **Example:** ```rust let result = instance.kind(); ``` **Returns:** `String` ###### kind\_id() [Section titled “kind\_id()”](#kind_id) Return the node’s numeric kind ID. Tree-sitter assigns a stable `u16` ID to every node kind in a grammar (e.g. `"function_definition" → 42`). Comparing `kind_id()` is cheaper than comparing the string `kind()` in tight AST loops. **Signature:** ```rust pub fn kind_id(&self) -> u16 ``` **Example:** ```rust let result = instance.kind_id(); ``` **Returns:** `u16` ###### start\_byte() [Section titled “start\_byte()”](#start_byte) Return the inclusive start byte offset of this node. **Signature:** ```rust pub fn start_byte(&self) -> usize ``` **Example:** ```rust let result = instance.start_byte(); ``` **Returns:** `usize` ###### end\_byte() [Section titled “end\_byte()”](#end_byte) Return the exclusive end byte offset of this node. **Signature:** ```rust pub fn end_byte(&self) -> usize ``` **Example:** ```rust let result = instance.end_byte(); ``` **Returns:** `usize` ###### byte\_range() [Section titled “byte\_range()”](#byte_range) Return the node’s byte range as a `ByteRange`. Callers should slice their own source bytes — this is a zero-copy text accessor. **Signature:** ```rust pub fn byte_range(&self) -> ByteRange ``` **Example:** ```rust let result = instance.byte_range(); ``` **Returns:** `ByteRange` ###### start\_position() [Section titled “start\_position()”](#start_position) Return the start `Point` (row, column). **Signature:** ```rust pub fn start_position(&self) -> Point ``` **Example:** ```rust let result = instance.start_position(); ``` **Returns:** `Point` ###### end\_position() [Section titled “end\_position()”](#end_position) Return the end `Point` (row, column). **Signature:** ```rust pub fn end_position(&self) -> Point ``` **Example:** ```rust let result = instance.end_position(); ``` **Returns:** `Point` ###### is\_named() [Section titled “is\_named()”](#is_named) True when this node is named (not punctuation/whitespace). **Signature:** ```rust pub fn is_named(&self) -> bool ``` **Example:** ```rust let result = instance.is_named(); ``` **Returns:** `bool` ###### is\_error() [Section titled “is\_error()”](#is_error) True when this is an error node. **Signature:** ```rust pub fn is_error(&self) -> bool ``` **Example:** ```rust let result = instance.is_error(); ``` **Returns:** `bool` ###### is\_missing() [Section titled “is\_missing()”](#is_missing) True when this is a missing-token node. **Signature:** ```rust pub fn is_missing(&self) -> bool ``` **Example:** ```rust let result = instance.is_missing(); ``` **Returns:** `bool` ###### is\_extra() [Section titled “is\_extra()”](#is_extra) True when this is an “extra” node (e.g. a comment). **Signature:** ```rust pub fn is_extra(&self) -> bool ``` **Example:** ```rust let result = instance.is_extra(); ``` **Returns:** `bool` ###### has\_error() [Section titled “has\_error()”](#has_error) True when this node or any descendant is an error. **Signature:** ```rust pub fn has_error(&self) -> bool ``` **Example:** ```rust let result = instance.has_error(); ``` **Returns:** `bool` ###### parent() [Section titled “parent()”](#parent) Return this node’s parent, if any. **Signature:** ```rust pub fn parent(&self) -> Option ``` **Example:** ```rust let result = instance.parent(); ``` **Returns:** `Option` ###### child() [Section titled “child()”](#child) Return the i-th child of this node, if any. **Signature:** ```rust pub fn child(&self, index: u32) -> Option ``` **Example:** ```rust let result = instance.child(42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | ----- | -------- | ----------- | | `index` | `u32` | Yes | The index | **Returns:** `Option` ###### child\_count() [Section titled “child\_count()”](#child_count) Total number of children (including unnamed). **Signature:** ```rust pub fn child_count(&self) -> usize ``` **Example:** ```rust let result = instance.child_count(); ``` **Returns:** `usize` ###### named\_child() [Section titled “named\_child()”](#named_child) Return the i-th named child of this node, if any. **Signature:** ```rust pub fn named_child(&self, index: u32) -> Option ``` **Example:** ```rust let result = instance.named_child(42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | ----- | -------- | ----------- | | `index` | `u32` | Yes | The index | **Returns:** `Option` ###### named\_child\_count() [Section titled “named\_child\_count()”](#named_child_count) Number of named children of this node. **Signature:** ```rust pub fn named_child_count(&self) -> usize ``` **Example:** ```rust let result = instance.named_child_count(); ``` **Returns:** `usize` ###### child\_by\_field\_name() [Section titled “child\_by\_field\_name()”](#child_by_field_name) Look up a child by its grammar-defined field name. **Signature:** ```rust pub fn child_by_field_name(&self, name: &str) -> Option ``` **Example:** ```rust let result = instance.child_by_field_name("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------ | -------- | ----------- | | `name` | `&str` | Yes | The name | **Returns:** `Option` ###### to\_sexp() [Section titled “to\_sexp()”](#to_sexp) Return the S-expression form of this node’s subtree. **Signature:** ```rust pub fn to_sexp(&self) -> String ``` **Example:** ```rust let result = instance.to_sexp(); ``` **Returns:** `String` ###### walk() [Section titled “walk()”](#walk) Return a `TreeCursor` positioned at this node. **Signature:** ```rust pub fn walk(&self) -> TreeCursor ``` **Example:** ```rust let result = instance.walk(); ``` **Returns:** `TreeCursor` *** #### PackConfig [Section titled “PackConfig”](#packconfig) Configuration for the tree-sitter language pack. Controls cache directory and which languages to pre-download. Can be loaded from a TOML file, constructed programmatically, or passed as a dict/object from language bindings. | Field | Type | Default | Description | | ----------- | --------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cache_dir` | `Option` | `Default::default()` | Override the BASE directory the parser cache lives under. This is a base, not the final library path: the crate appends `tree-sitter-language-pack/v{version}/libs` to it, exactly as it does to the platform default. So `cache_dir = "/tmp/my-parsers"` resolves to `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`. The suffix is not cosmetic. It keeps the whole cache tree — manifest, bundles and lock file included — inside a directory this library owns and versions. Earlier releases used this path verbatim, which put those files in the configured directory’s PARENT and let a cache built by one crate version be reused by another. Default base: the platform cache dir, e.g. `~/.cache` on Linux. | | `languages` | `Option>` | `vec![]` | Languages to pre-download on init. Each entry is a language name (e.g. `"python"`, `"rust"`). | | `groups` | `Option>` | `vec![]` | Language groups to pre-download. Group names come from the remote manifest, so the valid set is not fixed by this library; the published manifest currently defines only `"all"`. Call `manifest_groups` to enumerate them. An unknown name makes `init` fail. | *** #### Parser [Section titled “Parser”](#parser) A tree-sitter parser configured for one language at a time. ##### Methods [Section titled “Methods”](#methods-3) ###### new() [Section titled “new()”](#new-2) Construct a new parser with no language set and no parse limits. Call `Parser::set_language` before parsing. Limits are opt-in via `set_max_source_bytes` and `set_parse_timeout_ms`; both default to unbounded so that existing callers are unaffected. **Signature:** ```rust pub fn new() -> Parser ``` **Example:** ```rust let result = Parser::new(); ``` **Returns:** `Parser` ###### set\_max\_source\_bytes() [Section titled “set\_max\_source\_bytes()”](#set_max_source_bytes) Refuse to parse sources longer than `max_bytes`. `None` (the default) means no limit. Over-limit input makes `parse` and `parse_bytes` return `None` after emitting a `WARN`; input is never silently truncated. See `RECOMMENDED_MAX_SOURCE_BYTES`. **Signature:** ```rust pub fn set_max_source_bytes(&mut self, max_bytes: Option) ``` **Example:** ```rust instance.set_max_source_bytes(42); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | --------------- | -------- | ------------- | | `max_bytes` | `Option` | No | The max bytes | **Returns:** No return value. ###### set\_parse\_timeout\_ms() [Section titled “set\_parse\_timeout\_ms()”](#set_parse_timeout_ms) Cancel a parse that exceeds `timeout_ms` milliseconds of wall clock. `None` (the default) means no budget. Cancellation runs through tree-sitter’s parse progress callback, so it is granular to that callback’s interval rather than exact. See `RECOMMENDED_PARSE_TIMEOUT_MS`. **Signature:** ```rust pub fn set_parse_timeout_ms(&mut self, timeout_ms: Option) ``` **Example:** ```rust instance.set_parse_timeout_ms(42); ``` **Parameters:** | Name | Type | Required | Description | | ------------ | ------------- | -------- | -------------- | | `timeout_ms` | `Option` | No | The timeout ms | **Returns:** No return value. ###### set\_language() [Section titled “set\_language()”](#set_language) Configure the parser to use the language identified by name (e.g. `"python"`). Resolves the language through the global registry — auto-downloading if necessary, when the `download` feature is enabled. **Errors:** Returns `Error::LanguageNotFound` if the language is not recognized, or `Error::ParserSetup` if the language ABI is incompatible. **Signature:** ```rust pub fn set_language(&mut self, name: &str) -> Result<(), Error> ``` **Example:** ```rust instance.set_language("value")?; ``` **Parameters:** | Name | Type | Required | Description | | ------ | ------ | -------- | ----------- | | `name` | `&str` | Yes | The name | **Returns:** No return value. **Errors:** Returns `Err(Error)`. ###### parse() [Section titled “parse()”](#parse) Parse a UTF-8 source string. Returns `None` if no language is set, if the parse was cancelled by the configured timeout, or if the source exceeds the configured size limit. Each non-parse outcome is logged, so an empty result is never silent. ###### Concurrency [Section titled “Concurrency”](#concurrency) Parsing runs fully in parallel across threads for almost every language — no lock is taken. The exception is the small set of grammars whose external scanner keeps mutable process-global state (currently just `properties`): parses of that language are serialized against each other through an internal per-language lock, so that concurrent threads can’t corrupt shared scanner state. Every other language is unaffected by that lock and never waits on it. **Signature:** ```rust pub fn parse(&mut self, source: &str) -> Option ``` **Example:** ```rust let result = instance.parse("value"); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------ | -------- | ----------- | | `source` | `&str` | Yes | The source | **Returns:** `Option` ###### parse\_bytes() [Section titled “parse\_bytes()”](#parse_bytes) Parse a raw byte slice. Same outcomes as `parse`, including the concurrency behaviour documented there. **Signature:** ```rust pub fn parse_bytes(&mut self, source: &[u8]) -> Option ``` **Example:** ```rust let result = instance.parse_bytes(b"data"); ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------- | -------- | ----------- | | `source` | `&\[u8\]` | Yes | The source | **Returns:** `Option` ###### reset() [Section titled “reset()”](#reset) Reset internal state. The next call to `parse` will not be incremental. **Signature:** ```rust pub fn reset(&mut self) ``` **Example:** ```rust instance.reset(); ``` **Returns:** No return value. ###### default() [Section titled “default()”](#default-1) **Signature:** ```rust pub fn default() -> Parser ``` **Example:** ```rust let result = Parser::default(); ``` **Returns:** `Parser` *** #### Point [Section titled “Point”](#point) A source position — row + column, zero-indexed. | Field | Type | Default | Description | | -------- | ------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `row` | `usize` | — | Zero-indexed row number. | | `column` | `usize` | — | Zero-indexed column, counted in **bytes** from the start of the row. This is `tree_sitter::Point::column` verbatim, and tree-sitter defines it as a byte offset — not characters, and not UTF-16 code units. Measured on a row of the form `x = ''` where `` is a single 4-byte character (an emoji), the string node reports columns `4..10`, identical to its byte range; the character columns would be `4..7` and the UTF-16 columns `4..8`. Anything that builds LSP positions (UTF-16) or editor caret columns (characters) from this field is silently wrong on every row containing a non-ASCII byte, and must re-measure the row against the source text instead. Earlier releases documented this field as UTF-16 code units; that was never what the value contained. | *** #### ProcessConfig [Section titled “ProcessConfig”](#processconfig) Configuration for the `process()` function. Controls which analysis features are enabled and whether chunking is performed. | Field | Type | Default | Description | | ------------------ | --------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `language` | `String` | `""` | Language name (required). | | `structure` | `bool` | `true` | Extract structural items (functions, classes, etc.). Default: true. | | `imports` | `bool` | `true` | Extract import statements. Default: true. | | `exports` | `bool` | `true` | Extract export statements. Default: true. | | `comments` | `bool` | `false` | Extract comments. Default: false. | | `docstrings` | `bool` | `false` | Extract docstrings. Default: false. | | `symbols` | `bool` | `false` | Extract symbol definitions. Default: false. | | `diagnostics` | `bool` | `false` | Include parse diagnostics. Default: false. | | `chunk_max_size` | `Option` | `None` | Maximum chunk size in bytes. `None` disables chunking. `Some(0)` is rejected by `ProcessConfig::validate` with `Error::InvalidRange`. A zero-sized chunk limit previously produced an empty chunk list and silently discarded the whole source; use `None` to mean “do not chunk”. | | `data_extraction` | `bool` | `false` | Extract hierarchical key/value data tree from data-format files. Default: false. When `true`, `ProcessResult::data` is populated with a `DataNode` tree for supported languages: JSON, YAML, TOML, `.properties`, HCL/HOCON, INI, editorconfig, KDL, CUE, CSV, PSV, PO, nginx config, Caddy config, XML, and DTD. For languages outside this set the field is left as `None`. | | `max_source_bytes` | `Option` | `None` | Reject source longer than this many bytes instead of parsing it. Default: `None` (unbounded). Tree-sitter allocates and walks proportionally to input size, so an unbounded parse of attacker-supplied input is a denial-of-service vector. The default stays unbounded for backward compatibility; services handling untrusted input should opt in, e.g. with `RECOMMENDED_MAX_SOURCE_BYTES`. Exceeding the limit fails the call with `Error::InvalidRange` — the source is never silently truncated. | | `parse_timeout_ms` | `Option` | `None` | Wall-clock budget for the parse step, in milliseconds. Default: `None` (no timeout). Enforced through tree-sitter’s parse progress callback, which the parser invokes periodically; cancellation is therefore granular to that callback interval rather than exact. A parse that exceeds the budget fails with `Error::ParseTimeout`. | ##### Methods [Section titled “Methods”](#methods-4) ###### default() [Section titled “default()”](#default-2) **Signature:** ```rust pub fn default() -> ProcessConfig ``` **Example:** ```rust let result = ProcessConfig::default(); ``` **Returns:** `ProcessConfig` ###### with\_chunking() [Section titled “with\_chunking()”](#with_chunking) Enable chunking with the given maximum chunk size in bytes. **Signature:** ```rust pub fn with_chunking(self, max_size: usize) -> ProcessConfig ``` **Example:** ```rust let result = instance.with_chunking(42); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------- | -------- | ------------ | | `max_size` | `usize` | Yes | The max size | **Returns:** `ProcessConfig` ###### all() [Section titled “all()”](#all) Enable every analysis feature, including data extraction. Chunking is not an analysis feature and stays off; enable it with `with_chunking`. **Signature:** ```rust pub fn all(self) -> ProcessConfig ``` **Example:** ```rust let result = instance.all(); ``` **Returns:** `ProcessConfig` ###### minimal() [Section titled “minimal()”](#minimal) Disable all analysis features (only metrics computed). **Signature:** ```rust pub fn minimal(self) -> ProcessConfig ``` **Example:** ```rust let result = instance.minimal(); ``` **Returns:** `ProcessConfig` ###### with\_data\_extraction() [Section titled “with\_data\_extraction()”](#with_data_extraction) Enable or disable hierarchical data extraction for data-format files. When `true`, `ProcessResult::data` is populated with a key/value tree for supported data-format languages. **Signature:** ```rust pub fn with_data_extraction(self, enabled: bool) -> ProcessConfig ``` **Example:** ```rust let result = instance.with_data_extraction(true); ``` **Parameters:** | Name | Type | Required | Description | | --------- | ------ | -------- | ----------- | | `enabled` | `bool` | Yes | The enabled | **Returns:** `ProcessConfig` ###### with\_max\_source\_bytes() [Section titled “with\_max\_source\_bytes()”](#with_max_source_bytes) Reject source longer than `max_bytes` instead of parsing it. Pass `None` to restore the default unbounded behaviour. See `RECOMMENDED_MAX_SOURCE_BYTES` for a starting value. **Signature:** ```rust pub fn with_max_source_bytes(self, max_bytes: Option) -> ProcessConfig ``` **Example:** ```rust let result = instance.with_max_source_bytes(42); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | --------------- | -------- | ------------- | | `max_bytes` | `Option` | No | The max bytes | **Returns:** `ProcessConfig` ###### with\_parse\_timeout\_ms() [Section titled “with\_parse\_timeout\_ms()”](#with_parse_timeout_ms) Cancel the parse if it exceeds `timeout_ms` milliseconds of wall clock. Pass `None` to restore the default (no timeout). See `RECOMMENDED_PARSE_TIMEOUT_MS` for a starting value. **Signature:** ```rust pub fn with_parse_timeout_ms(self, timeout_ms: Option) -> ProcessConfig ``` **Example:** ```rust let result = instance.with_parse_timeout_ms(42); ``` **Parameters:** | Name | Type | Required | Description | | ------------ | ------------- | -------- | -------------- | | `timeout_ms` | `Option` | No | The timeout ms | **Returns:** `ProcessConfig` ###### validate() [Section titled “validate()”](#validate) Check that the configured limits are usable before they drive a parse. Called by `process` and `LanguageRegistry::process`; call it directly to reject a bad configuration early. **Errors:** Returns `Error::InvalidRange` when `chunk_max_size`, `max_source_bytes`, or `parse_timeout_ms` is `Some(0)`. Zero is always a configuration mistake: `None` is how each of these is disabled, so `Some(0)` could only mean “produce nothing”. **Signature:** ```rust pub fn validate(&self) -> Result<(), Error> ``` **Example:** ```rust instance.validate()?; ``` **Returns:** No return value. **Errors:** Returns `Err(Error)`. *** #### ProcessResult [Section titled “ProcessResult”](#processresult) Complete analysis result from processing a source file. Contains metrics, structural analysis, imports/exports, comments, docstrings, symbols, diagnostics, and optionally chunked code segments. Fields are populated based on the `ProcessConfig` flags. | Field | Type | Default | Description | | ------------- | -------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String` | — | The language name used to parse the source file. | | `metrics` | `FileMetrics` | — | File-level metrics (line counts, byte size, error count). | | `structure` | `Vec` | `vec![]` | Top-level structural items (functions, classes, etc.). | | `imports` | `Vec` | `vec![]` | Import statements extracted from the source. | | `exports` | `Vec` | `vec![]` | Export statements extracted from the source. | | `comments` | `Vec` | `vec![]` | Comments extracted from the source. | | `docstrings` | `Vec` | `vec![]` | Docstrings extracted from the source. | | `symbols` | `Vec` | `vec![]` | Symbol definitions (variables, types, functions) extracted from the source. | | `diagnostics` | `Vec` | `vec![]` | Parse diagnostics (syntax errors, missing nodes) from tree-sitter. | | `chunks` | `Vec` | `vec![]` | Syntax-aware code chunks produced when chunking is enabled. | | `data` | `Option` | `Default::default()` | Hierarchical data tree extracted when `config.data_extraction` is `true`. Populated for supported data-format languages (JSON, YAML, TOML, properties, HCL, INI, XML, CSV, and more). `None` when `data_extraction` is `false` (the default) or when the language is not a recognised data format. See `DataNode` for the shape of the returned tree. | *** #### Span [Section titled “Span”](#span) Byte and line/column range in source code. Represents both byte offsets (for slicing) and human-readable line/column positions (for display and diagnostics). | Field | Type | Default | Description | | -------------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `start_byte` | `usize` | — | Inclusive start byte offset in the source. | | `end_byte` | `usize` | — | Exclusive end byte offset in the source. | | `start_line` | `usize` | — | Zero-indexed line number of the span’s start. | | `start_column` | `usize` | — | Zero-indexed column of the span’s start, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | | `end_line` | `usize` | — | Zero-indexed line number of the span’s end. | | `end_column` | `usize` | — | Zero-indexed column of the span’s end, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | *** #### StructureItem [Section titled “StructureItem”](#structureitem) A structural item (function, class, struct, etc.) in source code. | Field | Type | Default | Description | | ------------- | -------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `kind` | `StructureKind` | `StructureKind::Function` | The kind of structural item. | | `name` | `Option` | `Default::default()` | The declared name of the item, if present. | | `visibility` | `Option` | `Default::default()` | Visibility modifier (e.g., `"pub"`, `"public"`, `"private"`). | | `span` | `Span` | — | Source span covering the entire item declaration. | | `children` | `Vec` | `vec![]` | Nested structural items (e.g., methods within a class). | | `decorators` | `Vec` | `vec![]` | Decorator or attribute names applied to the item. **Reserved: not yet populated.** Always empty, for every language. Recognising a decorator requires per-language grammar knowledge (a Python `decorated_definition` wrapper, Java/C# annotations, Rust attributes each have a different shape), which no extractor here implements yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | | `doc_comment` | `Option` | `Default::default()` | Documentation comment attached to the item, if any. The text of the comment (or run of comments) immediately preceding the item, with no blank line in between, when that comment is classified as a doc comment. Multiple adjacent single-line doc comments (Rust `///`) are joined with `\n` in source order. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`). `None` for every other language, and for a preceding comment that is not in doc-comment form (a plain `#` comment in Python, Ruby, or Elixir) — Python’s docstring convention is captured separately, as `DocstringInfo`, not through this field. | | `signature` | `Option` | `Default::default()` | Full signature text of the item (e.g., function parameters and return type). The item’s own source text from its start up to the start of its body (see `StructureItem::body_span`), trimmed of trailing whitespace — for example `fn add(a: i32, b: i32) -> i32` for a Rust function whose body is `{ a + b }`. `None` only when that text is empty, which does not happen for any item `StructureKind` currently reports. Populated for every language and kind this library extracts structure for, since it is derived from `body_span`’s boundary rather than per-language syntax. | | `body_span` | `Option` | `Default::default()` | Source span covering only the body of the item, if distinct from the declaration. | *** #### SymbolInfo [Section titled “SymbolInfo”](#symbolinfo) A symbol (variable, function, type, etc.) extracted from source code. | Field | Type | Default | Description | | ----------------- | ---------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `String` | — | The name of the symbol. | | `kind` | `SymbolKind` | `SymbolKind::Variable` | The kind of symbol (variable, function, class, etc.). | | `span` | `Span` | — | Source span covering the symbol definition. | | `type_annotation` | `Option` | `Default::default()` | Explicit type annotation, if present in the source. | | `doc` | `Option` | `Default::default()` | Documentation comment immediately preceding this symbol, resolved by the same walk `StructureItem::doc_comment` uses (see `doc_comment_at`) — never hard-coded `None`. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`) — the languages whose comment classification recognizes a doc-kind comment. `None` for every other language (e.g. Python, Go, Ruby, which have no doc-kind comment classification), and also `None` when a symbol in a supported language simply has no doc comment immediately above it. | *** #### Tree [Section titled “Tree”](#tree) A parsed syntax tree. Cheap to clone (refcount bump). ##### Methods [Section titled “Methods”](#methods-5) ###### root\_node() [Section titled “root\_node()”](#root_node) Return the root `Node` of this tree. **Signature:** ```rust pub fn root_node(&self) -> Node ``` **Example:** ```rust let result = instance.root_node(); ``` **Returns:** `Node` ###### walk() [Section titled “walk()”](#walk-1) Return a `TreeCursor` positioned at the root. **Signature:** ```rust pub fn walk(&self) -> TreeCursor ``` **Example:** ```rust let result = instance.walk(); ``` **Returns:** `TreeCursor` *** #### TreeCursor [Section titled “TreeCursor”](#treecursor) A cursor for traversing a `Tree`. ##### Methods [Section titled “Methods”](#methods-6) ###### node() [Section titled “node()”](#node-1) Return the `Node` at the cursor’s current position. **Signature:** ```rust pub fn node(&self) -> Node ``` **Example:** ```rust let result = instance.node(); ``` **Returns:** `Node` ###### goto\_first\_child() [Section titled “goto\_first\_child()”](#goto_first_child) Move the cursor to the first child of the current node. Returns `true` if a child existed. **Signature:** ```rust pub fn goto_first_child(&mut self) -> bool ``` **Example:** ```rust let result = instance.goto_first_child(); ``` **Returns:** `bool` ###### goto\_parent() [Section titled “goto\_parent()”](#goto_parent) Move the cursor to the parent of the current node. Returns `true` if a parent existed. **Signature:** ```rust pub fn goto_parent(&mut self) -> bool ``` **Example:** ```rust let result = instance.goto_parent(); ``` **Returns:** `bool` ###### goto\_next\_sibling() [Section titled “goto\_next\_sibling()”](#goto_next_sibling) Move the cursor to the next sibling of the current node. Returns `true` if a sibling existed. **Signature:** ```rust pub fn goto_next_sibling(&mut self) -> bool ``` **Example:** ```rust let result = instance.goto_next_sibling(); ``` **Returns:** `bool` ###### field\_name() [Section titled “field\_name()”](#field_name) Return the field name for the current node, if any. **Signature:** ```rust pub fn field_name(&self) -> Option ``` **Example:** ```rust let result = instance.field_name(); ``` **Returns:** `Option` *** ### Enums [Section titled “Enums”](#enums) #### DataNodeKind [Section titled “DataNodeKind”](#datanodekind) The kind of a data node extracted from a data-format file. Classifies each node in the hierarchical `DataNode` tree returned when `data_extraction` is enabled on `ProcessConfig`. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract) Unit variants serialize as a bare string (`"KeyValue"`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ---------- | -------------------------------------------------------------------------------------------------------------------- | | `KeyValue` | A key/value pair or mapping (json/toml/properties/yaml/hcl/cue/kdl pair, or a wrapper “object”/“mapping” container). | | `Element` | An XML element with a tag name in `key` and attributes in `attributes`. | | `Sequence` | A positional sequence item (JSON array element, YAML block sequence item, CSV/PSV row or cell). | *** #### StructureKind [Section titled “StructureKind”](#structurekind) The kind of structural item found in source code. Categorizes top-level and nested declarations such as functions, classes, structs, enums, traits, and more. Use `Other` for language-specific constructs that do not fit a standard category. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-1) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | ---------------------------------------------------------------------------------------------- | | `Function` | A free-standing or associated function. | | `Method` | A method defined inside a class, struct, trait, or impl block. | | `Class` | A class definition. | | `Struct` | A struct definition. | | `Interface` | An interface or protocol definition. | | `Enum` | An enum definition. | | `Module` | A module or package declaration. | | `Trait` | A trait definition. | | `Impl` | An impl block (Rust) or similar implementation block. | | `Namespace` | A namespace declaration. | | `Other` | A language-specific construct that does not fit any standard category. — Fields: `0`: `String` | *** #### CommentKind [Section titled “CommentKind”](#commentkind) The kind of a comment found in source code. Distinguishes between single-line comments, block (multi-line) comments, and documentation comments. | Value | Description | | ------- | --------------------------------------------------------------------- | | `Line` | A single-line comment (e.g., `// ...` or `# ...`). | | `Block` | A block or multi-line comment using slash-star delimiters. | | `Doc` | A documentation comment such as `/// ...` or slash-double-star block. | *** #### DocstringFormat [Section titled “DocstringFormat”](#docstringformat) The format of a docstring extracted from source code. Identifies the docstring convention used, which varies by language (e.g., Python triple-quoted strings, JSDoc, Rustdoc `///` comments). ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-2) Unit variants serialize as a bare string (`"JSDoc"`); the `Other` variant serializes as a single-keyed object (`{"Other": "rst"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ------------------- | -------------------------------------------------------------------------------------------------- | | `PythonTripleQuote` | Python triple-quoted string docstring (`"""..."""`). | | `JsDoc` | JavaScript/TypeScript JSDoc block comment (opens with two stars, closes with star-slash). | | `Rustdoc` | Rust `///` or `//!` doc comment. | | `GoDoc` | Go doc comment (a comment block immediately preceding a declaration). | | `JavaDoc` | Java Javadoc block comment (opens with two stars, closes with star-slash). | | `Other` | A language-specific docstring format not covered by the standard variants. — Fields: `0`: `String` | *** #### ExportKind [Section titled “ExportKind”](#exportkind) The kind of an export statement found in source code. Covers named exports, default exports, and re-exports from other modules. | Value | Description | | ---------- | -------------------------------------------------------------------- | | `Named` | A named export (e.g., `export { foo }`). | | `Default` | A default export (e.g., `export default foo`). | | `ReExport` | A re-export from another module (e.g., `export { foo } from 'bar'`). | *** #### SymbolKind [Section titled “SymbolKind”](#symbolkind) The kind of a symbol definition found in source code. Categorizes symbol definitions such as variables, constants, functions, classes, types, interfaces, enums, and modules. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-3) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | --------------------------------------------------------------------------- | | `Variable` | A variable binding. | | `Constant` | A constant (immutable binding). | | `Function` | A function definition. | | `Class` | A class definition. | | `Type` | A type alias or typedef. | | `Interface` | An interface definition. | | `Enum` | An enum definition. | | `Module` | A module declaration. | | `Other` | A symbol kind not covered by the standard variants. — Fields: `0`: `String` | *** #### DiagnosticSeverity [Section titled “DiagnosticSeverity”](#diagnosticseverity) Severity level of a diagnostic produced during parsing. Used to classify parse errors, warnings, and informational messages found in the syntax tree. | Value | Description | | --------- | --------------------------------------------------------------- | | `Error` | A parse error (e.g., an `ERROR` or `MISSING` node in the tree). | | `Warning` | A warning-level diagnostic. | | `Info` | An informational diagnostic. | *** ### Errors [Section titled “Errors”](#errors) #### Error [Section titled “Error”](#error) Errors that can occur when using the tree-sitter language pack. Covers language lookup failures, parse errors, query errors, and I/O issues. Feature-gated variants are included when `config`, `download`, or related features are enabled. ##### Matching on `Error` [Section titled “Matching on Error”](#matching-on-error) The set of variants is not stable: new failure modes are added in minor releases, and `Io`, `Json`, and `Toml` exist only under certain feature combinations, so the variant set a downstream crate sees depends on which features it enables. Downstream `match`es must therefore carry a `_` arm; `#[non_exhaustive]` makes the compiler enforce that instead of letting a feature change silently break a build. ##### C ABI error codes [Section titled “C ABI error codes”](#c-abi-error-codes) Each variant alef can see carries an explicit `alef(error_code = N)` allocation that becomes a member of the generated `AlefFfiErrorCode` C enum. These numbers are a public ABI contract: **an allocated number is never reused after its variant is removed**, and a variant’s number never changes, because C callers compare against the value, not the name. New variants take the next free number. 0-4 are reserved by alef, so allocation starts at 100. An unannotated variant is emitted as the unknown code rather than as itself, which silently flattens the taxonomy — annotate every new variant. | Variant | Description | | --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `LanguageNotFound` | The requested language name (or alias) was not found in the registry. | | `DynamicLoad` | A dynamic shared library could not be loaded at runtime. | | `NullLanguagePointer` | The tree-sitter language function returned a null pointer for the given language name. | | `ParserSetup` | The language could not be applied to the parser (e.g., ABI version mismatch). | | `LockPoisoned` | An internal `RwLock` or `Mutex` was poisoned by a previous panic. | | `Config` | A configuration file or value was invalid or could not be applied. | | `ParseFailed` | The tree-sitter parser returned no tree for the given source input. | | `ParseTimeout` | The parse was cancelled because it exceeded its configured wall-clock budget. Raised only when a budget is configured — see `ProcessConfig::parse_timeout_ms`, which defaults to `None`. | | `QueryError` | A tree-sitter query could not be compiled or executed. | | `InvalidRange` | A byte range was invalid (e.g., end before start, or out of bounds). | | `Download` | A parser download from GitHub releases failed. | | `ChecksumMismatch` | The downloaded file’s SHA-256 digest did not match the manifest’s expected value. | | `CacheLock` | The cross-process download cache lock file could not be acquired or created. | *** # Swift API Reference ## Swift API Reference v1.16.1 [Section titled “Swift API Reference v1.16.1”](#swift-api-reference-v1161) ### Functions [Section titled “Functions”](#functions) #### detectLanguageFromExtension() [Section titled “detectLanguageFromExtension()”](#detectlanguagefromextension) Detect language name from a file extension (without leading dot). Returns `null` for unrecognized extensions. The match is case-insensitive. **Signature:** ```swift public static func detectLanguageFromExtension(ext: String) -> String? ``` **Example:** ```swift let result = detectLanguageFromExtension("value") ``` **Parameters:** | Name | Type | Required | Description | | ----- | -------- | -------- | ----------- | | `ext` | `String` | Yes | The ext | **Returns:** `String?` *** #### detectLanguageFromPath() [Section titled “detectLanguageFromPath()”](#detectlanguagefrompath) Detect language name from a file path. Extracts the file extension and looks it up. Returns `null` if the path has no extension or the extension is not recognized. **Signature:** ```swift public static func detectLanguageFromPath(path: String) -> String? ``` **Example:** ```swift let result = detectLanguageFromPath("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `path` | `String` | Yes | Path to the file | **Returns:** `String?` *** #### detectLanguageFromContent() [Section titled “detectLanguageFromContent()”](#detectlanguagefromcontent) Detect language name from file content using the shebang line (`#!`). Inspects only the first line of `content`. If it begins with `#!`, the interpreter name is extracted and mapped to a language name. Handles common patterns: * `#!/usr/bin/env python3` → `"python"` * `#!/bin/bash` → `"bash"` * `#!/usr/bin/env node` → `"javascript"` The `-S` flag accepted by some `env` implementations is skipped automatically. Version suffixes (e.g. `python3.11`, `ruby3.2`) are stripped before matching. A leading UTF-8 BOM (`U+FEFF`) is skipped before the `#!` check, so a BOM-prefixed script is still detected by its shebang. Returns `null` when content does not start with `#!` (after stripping a leading BOM), the shebang is malformed, or the interpreter is not recognised. **Signature:** ```swift public static func detectLanguageFromContent(content: String) -> String? ``` **Example:** ```swift let result = detectLanguageFromContent("value") ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ---------------------- | | `content` | `String` | Yes | The content to process | **Returns:** `String?` *** #### getHighlightsQuery() [Section titled “getHighlightsQuery()”](#gethighlightsquery) Get the highlights query for a language, if bundled. Returns the contents of `highlights.scm` as a static string, or `null` if no highlights query is bundled for this language. **Signature:** ```swift public static func getHighlightsQuery(language: String) -> String? ``` **Example:** ```swift let result = getHighlightsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getInjectionsQuery() [Section titled “getInjectionsQuery()”](#getinjectionsquery) Get the injections query for a language, if bundled. Returns the contents of `injections.scm` as a static string, or `null` if no injections query is bundled for this language. **Signature:** ```swift public static func getInjectionsQuery(language: String) -> String? ``` **Example:** ```swift let result = getInjectionsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getLocalsQuery() [Section titled “getLocalsQuery()”](#getlocalsquery) Get the locals query for a language, if bundled. Returns the contents of `locals.scm` as a static string, or `null` if no locals query is bundled for this language. **Signature:** ```swift public static func getLocalsQuery(language: String) -> String? ``` **Example:** ```swift let result = getLocalsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getTagsQuery() [Section titled “getTagsQuery()”](#gettagsquery) Get the tags query for a language, if bundled. Returns the contents of `tags.scm` as a static string, or `null` if no tags query is bundled for this language. **Signature:** ```swift public static func getTagsQuery(language: String) -> String? ``` **Example:** ```swift let result = getTagsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getIndentsQuery() [Section titled “getIndentsQuery()”](#getindentsquery) Get the indents query for a language, if bundled. Returns the contents of `indents.scm` (used for auto-indentation) as a static string, or `null` if no indents query is bundled for this language. **Signature:** ```swift public static func getIndentsQuery(language: String) -> String? ``` **Example:** ```swift let result = getIndentsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getFoldsQuery() [Section titled “getFoldsQuery()”](#getfoldsquery) Get the folds query for a language, if bundled. Returns the contents of `folds.scm` (used for code folding) as a static string, or `null` if no folds query is bundled for this language. **Signature:** ```swift public static func getFoldsQuery(language: String) -> String? ``` **Example:** ```swift let result = getFoldsQuery("value") ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `String` | Yes | The language | **Returns:** `String?` *** #### getLanguage() [Section titled “getLanguage()”](#getlanguage) Get a tree-sitter `Language` by name using the global registry. Resolves language aliases (e.g., `"shell"` maps to `"bash"`). When the `download` feature is enabled (default), automatically downloads the parser from GitHub releases if not found locally. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.Download` if auto-download fails. **Signature:** ```swift public static func getLanguage(name: String) throws -> Language ``` **Example:** ```swift let result = try getLanguage("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Language` **Errors:** Throws `Error`. *** #### getParser() [Section titled “getParser()”](#getparser) Get a `Parser` pre-configured for the given language. This is a convenience function that calls `get_language` and configures a new parser in one step. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language cannot be applied to the parser. **Signature:** ```swift public static func getParser(name: String) throws -> Parser ``` **Example:** ```swift let result = try getParser("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Parser` **Errors:** Throws `Error`. *** #### detectLanguage() [Section titled “detectLanguage()”](#detectlanguage) Detect language name from a file path or extension. This compatibility alias matches the pre-Alef Python binding API. **Signature:** ```swift public static func detectLanguage(path: String) -> String? ``` **Example:** ```swift let result = detectLanguage("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `path` | `String` | Yes | Path to the file | **Returns:** `String?` *** #### availableLanguages() [Section titled “availableLanguages()”](#availablelanguages) List all available language names (sorted, deduplicated, includes aliases). Returns names of both statically compiled and dynamically loadable languages, plus any configured aliases. **Signature:** ```swift public static func availableLanguages() -> [String] ``` **Example:** ```swift let result = availableLanguages() ``` **Returns:** `[String]` *** #### hasLanguage() [Section titled “hasLanguage()”](#haslanguage) Check if a language is available by name or alias. Returns `true` if the language can be loaded (statically compiled, dynamically available, or a known alias for one of these). **Signature:** ```swift public static func hasLanguage(name: String) -> Bool ``` **Example:** ```swift let result = hasLanguage("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Bool` *** #### languageCount() [Section titled “languageCount()”](#languagecount) Return the number of available languages. Includes statically compiled languages, dynamically loadable languages, and aliases. **Signature:** ```swift public static func languageCount() -> UInt ``` **Example:** ```swift let result = languageCount() ``` **Returns:** `UInt` *** #### process() [Section titled “process()”](#process) Process source code and extract file intelligence using the global registry. Parses the source with tree-sitter and extracts metrics, structure, imports, exports, comments, docstrings, symbols, diagnostics, and/or chunks based on the flags set in `ProcessConfig`. **Errors:** Returns `Error.InvalidRange` if the config carries a zero-valued limit or the source exceeds `ProcessConfig.max_source_bytes`, `Error.ParseTimeout` if the parse exceeds `ProcessConfig.parse_timeout_ms`, `Error.LanguageNotFound` if the language is unknown, or `Error.ParseFailed` if parsing yields no tree. **Signature:** ```swift public static func process(source: String, config: ProcessConfig) throws -> ProcessResult ``` **Example:** ```swift let result = try process("value", ProcessConfig()) ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `String` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Throws `Error`. *** #### init\_() [Section titled “init\_()”](#init_) Initialize the language pack with the given configuration. Applies any custom cache directory, then downloads all languages and groups specified in the config. This is the recommended entry point when you want to pre-warm the cache before use. **Errors:** Returns an error if configuration cannot be applied or if downloads fail. **Signature:** ```swift public static func init_(config: PackConfig) throws ``` **Example:** ```swift try init_(PackConfig()) ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Throws `Error`. *** #### configure() [Section titled “configure()”](#configure) Apply download configuration without downloading anything. Use this to set a custom cache directory before the first call to `get_language` or any download function. Changing the cache dir after languages have been registered has no effect on already-loaded languages. `PackConfig.cache_dir` is a BASE directory, not the final libs path: this crate appends `tree-sitter-language-pack/v{version}/libs` to it, the same suffix applied to the platform default cache directory. In the example below, files actually land under `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`, never directly in `/tmp/my-parsers/`. Call `cache_dir` to read back the resolved, fully-suffixed path. **Errors:** Returns an error if the lock cannot be acquired. **Signature:** ```swift public static func configure(config: PackConfig) throws ``` **Example:** ```swift try configure(PackConfig()) ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Throws `Error`. *** #### download() [Section titled “download()”](#download) Download specific languages to the local cache. Returns the number of distinct languages available after the call. Already compiled or cached languages are included in the count. Aliases are resolved before counting, so `["shell", "bash"]` names one language and returns 1. **Errors:** Returns an error if any language is not available in the manifest or if the download fails. **Signature:** ```swift public static func download(names: [String]) throws -> UInt ``` **Example:** ```swift let result = try download([]) ``` **Parameters:** | Name | Type | Required | Description | | ------- | ------------ | -------- | ----------- | | `names` | `\[String\]` | Yes | The names | **Returns:** `UInt` **Errors:** Throws `Error`. *** #### prefetch() [Section titled “prefetch()”](#prefetch) Prefetch grammars: download any not already loadable from disk, then load every requested language into the process registry so a subsequent hot loop only parses. Unlike `download()`, this does not trust in-memory availability — it downloads whenever a grammar is not actually loadable from disk (fixing the case where a known-but-not-downloaded grammar is reported present), then resolves and caches every requested language. Call it once, up front, before a parallel workload. **Errors:** Returns `Error.Download` if a required grammar cannot be fetched, or `Error.LanguageNotFound` if a requested name is unknown. **Signature:** ```swift public static func prefetch(languages: [String]) throws ``` **Example:** ```swift try prefetch([]) ``` **Parameters:** | Name | Type | Required | Description | | ----------- | ------------ | -------- | ------------- | | `languages` | `\[String\]` | Yes | The languages | **Returns:** No return value. **Errors:** Throws `Error`. *** #### downloadAll() [Section titled “downloadAll()”](#downloadall) Download all available languages from the remote manifest. Downloads the platform bundle and extracts every library it contains. Languages that appear in the manifest but are absent from the bundle (e.g. grammars that failed to compile at release time) are silently skipped — they are not treated as an error. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns an error if the manifest cannot be fetched or the bundle download fails. **Signature:** ```swift public static func downloadAll() throws -> UInt ``` **Example:** ```swift let result = try downloadAll() ``` **Returns:** `UInt` **Errors:** Throws `Error`. *** #### downloadGroup() [Section titled “downloadGroup()”](#downloadgroup) Download every language in a named group. Groups are defined by the remote manifest, not by this library, and let you ensure a curated set of related grammars in one call instead of listing each name to `download()`. Already-cached languages are skipped. Call `manifest_groups` to discover the group names the manifest actually defines. The published manifest currently defines a single group, `"all"`; earlier revisions of this documentation advertised `"web"`, `"data"`, and `"systems"`, which the manifest has never contained, so every call following that example failed. Do not hardcode a group name without checking. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns `Error.Download` if the manifest cannot be fetched, if the group is unknown — the message lists the groups the manifest defines — or if any constituent language fails to download. **Signature:** ```swift public static func downloadGroup(name: String) throws -> UInt ``` **Example:** ```swift let result = try downloadGroup("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `UInt` **Errors:** Throws `Error`. *** #### manifestLanguages() [Section titled “manifestLanguages()”](#manifestlanguages) Return all language names available in the remote manifest (371). Fetches (and caches) the remote manifest to discover the full list of downloadable languages. Use `downloaded_languages` to list what is already cached locally. **Errors:** Returns an error if the manifest cannot be fetched. **Signature:** ```swift public static func manifestLanguages() throws -> [String] ``` **Example:** ```swift let result = try manifestLanguages() ``` **Returns:** `[String]` **Errors:** Throws `Error`. *** #### manifestGroups() [Section titled “manifestGroups()”](#manifestgroups) Return the names of every language group the remote manifest defines, sorted. Group names are manifest data, not a compile-time constant of this library, so this is the only reliable way to learn what `download_group` and `PackConfig.groups` accept. The published manifest currently defines just `"all"`. **Errors:** Returns `Error.Download` if the manifest cannot be fetched. **Signature:** ```swift public static func manifestGroups() throws -> [String] ``` **Example:** ```swift let result = try manifestGroups() ``` **Returns:** `[String]` **Errors:** Throws `Error`. *** #### downloadedLanguages() [Section titled “downloadedLanguages()”](#downloadedlanguages) Return languages that are already downloaded and cached locally. Does not perform any network requests. Returns an empty list if the cache directory does not exist or cannot be read. **Signature:** ```swift public static func downloadedLanguages() -> [String] ``` **Example:** ```swift let result = downloadedLanguages() ``` **Returns:** `[String]` *** #### cleanCache() [Section titled “cleanCache()”](#cleancache) Delete all cached parser shared libraries. Resets the cache registration so the next call to `get_language` or a download function will re-register the (now empty) cache directory. **Errors:** Returns an error if the cache directory cannot be removed. **Signature:** ```swift public static func cleanCache() throws ``` **Example:** ```swift try cleanCache() ``` **Returns:** No return value. **Errors:** Throws `Error`. *** #### cacheDir() [Section titled “cacheDir()”](#cachedir) Return the effective cache directory path. This is `{base}/tree-sitter-language-pack/v{version}/libs/`, where `{base}` is either the custom BASE directory set via `configure` / `init` (`PackConfig.cache_dir`) or the platform default cache directory — both are suffixed identically, so a custom `cache_dir` is never used as the final libs path. The default resolves to `~/.cache/tree-sitter-language-pack/v{version}/libs/` on a typical Unix system. **Errors:** Returns an error if no cache directory can be resolved: `version` is somehow invalid, or (with no custom `cache_dir` configured) the platform reports none and `TREE_SITTER_LANGUAGE_PACK_CACHE_DIR` is unset. This crate no longer falls back to the temporary directory for the latter case — see #101 H2. **Signature:** ```swift public static func cacheDir() throws -> String ``` **Example:** ```swift let result = try cacheDir() ``` **Returns:** `String` **Errors:** Throws `Error`. *** ### Types [Section titled “Types”](#types) #### ByteRange [Section titled “ByteRange”](#byterange) A byte range — start (inclusive) to end (exclusive). | Field | Type | Default | Description | | ------- | ------ | ------- | ---------------------------- | | `start` | `UInt` | — | Inclusive start byte offset. | | `end` | `UInt` | — | Exclusive end byte offset. | *** #### ChunkContext [Section titled “ChunkContext”](#chunkcontext) Metadata for a single chunk of source code. | Field | Type | Default | Description | | ---------------- | ------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String` | — | Language name used to parse this chunk. | | `chunkIndex` | `UInt` | — | Zero-indexed position of this chunk within the file’s chunk list. | | `totalChunks` | `UInt` | — | Total number of chunks the file was split into. | | `nodeTypes` | `\[String\]` | `[]` | Tree-sitter node kinds that appear at the top level of this chunk. | | `contextPath` | `\[String\]` | `[]` | Hierarchical path of enclosing structural items (e.g., `["MyClass", "my_method"]`). | | `symbolsDefined` | `\[String\]` | `[]` | Names of symbols defined within this chunk. | | `comments` | `\[CommentInfo\]` | `[]` | Comments contained within this chunk. | | `docstrings` | `\[DocstringInfo\]` | `[]` | Docstrings contained within this chunk. Populated only for Python — the same language for which `ProcessResult.docstrings` is populated, and by the same classifier. Always empty for every other language. | | `hasErrorNodes` | `Bool` | — | Whether this chunk contains any tree-sitter error nodes. | *** #### CodeChunk [Section titled “CodeChunk”](#codechunk) A chunk of source code with rich metadata. | Field | Type | Default | Description | | ----------- | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `content` | `String` | — | The raw source text of this chunk. | | `startByte` | `UInt` | — | Inclusive start byte offset of this chunk in the original source. | | `endByte` | `UInt` | — | Exclusive end byte offset of this chunk in the original source. | | `startLine` | `UInt` | — | Zero-indexed start line of this chunk. | | `endLine` | `UInt` | — | Zero-indexed row of the last byte actually included in this chunk (inclusive — the same row a `Span.end_line` would report for a node ending on that byte). Computed the same way regardless of whether the source has a trailing newline: it is always the row of `end_byte - 1`, never a phantom row past the file’s real content. | | `metadata` | `ChunkContext` | — | Contextual metadata about this chunk. | *** #### CommentInfo [Section titled “CommentInfo”](#commentinfo) A comment extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------- | ------------------ | ----------------------------------------------------------------- | | `text` | `String` | — | The raw text content of the comment. | | `kind` | `CommentKind` | `CommentKind.line` | The kind of comment (line, block, or doc). | | `span` | `Span` | — | Source span covering the comment. | | `associatedNode` | `String?` | `null` | Name of the syntax node this comment is directly associated with. | *** #### DataAttribute [Section titled “DataAttribute”](#dataattribute) An XML-style attribute attached to an `Element` node. Populated only for `DataNodeKind.Element`; always empty for `KeyValue` and `Sequence` nodes. | Field | Type | Default | Description | | ------- | -------- | ------- | --------------------------------------------------------------- | | `name` | `String` | — | Attribute name (e.g. `"class"`, `"href"`). | | `value` | `String` | — | Attribute value as a raw string (quotes stripped). | | `span` | `Span` | — | Source span covering the entire `name="value"` attribute token. | *** #### DataNode [Section titled “DataNode”](#datanode) A node in the hierarchical data tree produced by data-format extraction. When `ProcessConfig.data_extraction` is `true`, `ProcessResult.data` is populated with a root `DataNode` whose `children` mirror the structure of the parsed file. The `kind` field determines which other fields are meaningful: | `kind` | `key` | `value` | `attributes` | `children` | | ---------- | ------------------------- | ------------ | ------------ | -------------- | | `KeyValue` | key / mapping key / index | leaf value | empty | nested map | | `Element` | XML tag name | text content | XML attrs | child elements | | `Sequence` | positional index (`"0"`) | leaf value | empty | sub-items | | Field | Type | Default | Description | | ------------ | ------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------- | | `kind` | `DataNodeKind` | `DataNodeKind.keyValue` | Whether this node is a key/value pair, XML element, or sequence item. | | `key` | `String?` | `null` | Key, attribute name, tag name, or positional index (`"0"`, `"1"`, …). `null` at the document root. | | `value` | `String?` | `null` | Leaf scalar value, if any. `null` for containers (objects, arrays, XML elements with child elements). | | `attributes` | `\[DataAttribute\]` | `[]` | Attributes on element-shape nodes (XML `STag` attributes). Empty for all other kinds. | | `children` | `\[DataNode\]` | `[]` | Children for nested containers and XML element bodies. | | `span` | `Span` | — | Source span covering this node in the original source file. | *** #### Diagnostic [Section titled “Diagnostic”](#diagnostic) A diagnostic (syntax error, missing node, etc.) from parsing. | Field | Type | Default | Description | | ---------- | -------------------- | -------------------------- | ---------------------------------------------- | | `message` | `String` | — | Human-readable description of the diagnostic. | | `severity` | `DiagnosticSeverity` | `DiagnosticSeverity.error` | Severity of the diagnostic. | | `span` | `Span` | — | Source span where the diagnostic was detected. | *** #### DocSection [Section titled “DocSection”](#docsection) A section within a docstring (e.g., Args, Returns, Raises). | Field | Type | Default | Description | | ------------- | --------- | ------- | ------------------------------------------------------- | | `kind` | `String` | — | Section kind (e.g., `"args"`, `"returns"`, `"raises"`). | | `name` | `String?` | `null` | Parameter or return value name, if applicable. | | `description` | `String` | — | Description text for this section. | *** #### DocstringInfo [Section titled “DocstringInfo”](#docstringinfo) A docstring extracted from source code. | Field | Type | Default | Description | | ---------------- | ----------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | `String` | — | The raw text of the docstring. | | `format` | `DocstringFormat` | `DocstringFormat.pythonTripleQuote` | The docstring format (Python, JSDoc, Rustdoc, etc.). | | `span` | `Span` | — | Source span covering the docstring. | | `associatedItem` | `String?` | `null` | Name of the item this docstring documents. | | `parsedSections` | `\[DocSection\]` | `[]` | Parsed sections of the docstring (Args, Returns, Raises, etc.). **Reserved: not yet populated.** Always empty, for every `DocstringFormat`. Parsing a docstring body into sections requires implementing each convention’s own layout (Google/NumPy/reST style for Python, `@param`/`@returns` for JSDoc/Javadoc, and so on), which no extractor here does yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | *** #### DownloadManager [Section titled “DownloadManager”](#downloadmanager) Manages downloading and caching of pre-built parser shared libraries. ##### Methods [Section titled “Methods”](#methods) ###### new() [Section titled “new()”](#new) Create a new download manager for the given version. **Errors:** Returns `Error.Download` if `version` is empty, contains a path separator or `..`, or contains a character outside `[A-Za-z0-9.+-]` — see `validate_version` — or if no cache directory can be resolved (see `Self.default_cache_dir`). **Signature:** ```swift public init(version: String) throws ``` **Example:** ```swift let result = try DownloadManager.new("value") ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ----------- | | `version` | `String` | Yes | The version | **Returns:** `DownloadManager` **Errors:** Throws `Error`. ###### installedLanguages() [Section titled “installedLanguages()”](#installedlanguages) List languages that are already downloaded and cached. Derived from the on-disk cache filenames, one canonical name per file, plus every alias that resolves to it (via `aliases_for`) — so this list agrees with the user-facing `LanguageRegistry.available_languages` about which names are “available”; both report `"shell"` once `bash` is cached, for example. A previous version reported canonical names only, which could never agree with `available_languages()`. See #107. Returns an empty list if the cache directory does not exist. If it exists but cannot be read (e.g. a permission error), also returns an empty list — changing this to a `Result` would be a breaking change across every language binding — but logs a `tracing.warn!` so the failure is not silently indistinguishable from “nothing installed”. **Signature:** ```swift public func installedLanguages() -> [String] ``` **Example:** ```swift let result = instance.installedLanguages() ``` **Returns:** `[String]` ###### downloadAllBestEffort() [Section titled “downloadAllBestEffort()”](#downloadallbesteffort) Download the platform bundle and extract every library file it contains. Unlike `Self.ensure_languages`, this does not check the manifest language list against archive contents — it simply extracts all `.so`/`.dylib`/`.dll` files from the bundle. Languages in the manifest that are missing from the archive are silently ignored rather than returning an error. Returns the number of library files extracted (including those already cached). **Signature:** ```swift public func downloadAllBestEffort() throws -> UInt ``` **Example:** ```swift let result = try instance.downloadAllBestEffort() ``` **Returns:** `UInt` **Errors:** Throws `Error`. ###### cleanCache() [Section titled “cleanCache()”](#cleancache-1) Remove all cached parser libraries. Acquires the cross-process lock so `clean_cache` cannot race a concurrent downloader (avoids Windows sharing-violation errors against an in-flight bundle write). The `.download.lock` file itself is **not** removed — it is permanent infrastructure; deleting it could allow a concurrent process that already opened the file to continue holding a stale lock handle while a new process opens a fresh inode, breaking the mutual-exclusion guarantee. **Signature:** ```swift public func cleanCache() throws ``` **Example:** ```swift try instance.cleanCache() ``` **Returns:** No return value. **Errors:** Throws `Error`. *** #### ExportInfo [Section titled “ExportInfo”](#exportinfo) An export statement extracted from source code. | Field | Type | Default | Description | | ------ | ------------ | ------------------ | -------------------------------------------------- | | `name` | `String` | — | The exported name. | | `kind` | `ExportKind` | `ExportKind.named` | The kind of export (named, default, or re-export). | | `span` | `Span` | — | Source span covering the export statement. | *** #### FileMetrics [Section titled “FileMetrics”](#filemetrics) Aggregate metrics for a source file. | Field | Type | Default | Description | | -------------- | ------ | ------- | -------------------------------------------------------------- | | `totalLines` | `UInt` | — | Total number of lines (including blank and comment lines). | | `codeLines` | `UInt` | — | Number of lines containing non-blank, non-comment source code. | | `commentLines` | `UInt` | — | Number of lines that are entirely comments. | | `blankLines` | `UInt` | — | Number of blank (whitespace-only) lines. | | `totalBytes` | `UInt` | — | Total byte length of the source file. | | `nodeCount` | `UInt` | — | Total number of nodes in the syntax tree. | | `errorCount` | `UInt` | — | Number of error nodes in the syntax tree (parse errors). | | `maxDepth` | `UInt` | — | Maximum nesting depth reached in the syntax tree. | *** #### ImportInfo [Section titled “ImportInfo”](#importinfo) An import statement extracted from source code. | Field | Type | Default | Description | | ------------ | ------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `source` | `String` | — | The module or path being imported from. | | `items` | `\[String\]` | `[]` | Specific names imported from the source module. For `import a, b` / `from m import a, b`, every entry’s base name (never the alias). For a JavaScript/TypeScript named-imports clause (`import { a, b as c } from 'm'`), every specifier’s original name. Populated for Python and JavaScript/TypeScript only. Always empty for every other language this library recognises import statements for — Rust, Go, Java, Kotlin, and Elixir (`import`/`alias`/`require`/`use`) — and for a JS/TS namespace import (`import * as ns`) or default import (`import x from 'm'`), neither of which names individual items. | | `alias` | `String?` | `null` | Alias assigned to the import (e.g., `import numpy as np`). Populated for Python’s single-name form (`import numpy as np`, `from m import a as b`) and JavaScript/TypeScript’s namespace form (`import * as ns from 'm'`) or a named-imports clause naming exactly one specifier (`import { a as b } from 'm'`). `null` for Rust, Go, Java, Kotlin, and Elixir (which has its own `as:` alias option on `alias` directives, not yet extracted here) — and for a Python statement that aliases several names at once (`import os, sys as s`), where there is no single alias to report for the statement as a whole, so only `items` is populated for it. | | `isWildcard` | `Bool` | — | Whether this is a wildcard import (e.g., `import *` or `use foo.*`). Detected from the syntax tree — a dedicated wildcard node (`wildcard_import` in Python, `use_wildcard` in Rust) or a bare `*` token outside of string-literal content — not by searching the import’s source text for a `*` character, so a glob in an import path string (`import a from './glob*.js'`) is not mistaken for one. | | `span` | `Span` | — | Source span covering the import statement. | *** #### Language [Section titled “Language”](#language) *** #### LanguageRegistry [Section titled “LanguageRegistry”](#languageregistry) Thread-safe registry of tree-sitter language parsers. Manages both statically compiled and dynamically loaded language grammars. Use `LanguageRegistry.new()` for the default registry, or access the global instance via the module-level convenience functions (`get_language`, `available_languages`, etc.). ##### Methods [Section titled “Methods”](#methods-1) ###### new() [Section titled “new()”](#new-1) Create a new registry populated with all statically compiled languages. When the `dynamic-loading` feature is enabled, the registry also knows about dynamically loadable grammars and will load them on demand. **Signature:** ```swift public init() ``` **Example:** ```swift let result = LanguageRegistry.new() ``` **Returns:** `LanguageRegistry` ###### getLanguage() [Section titled “getLanguage()”](#getlanguage-1) Get a tree-sitter `Language` by name. Resolves aliases (e.g., `"shell"` -> `"bash"`, `"makefile"` -> `"make"`), then looks up the language in the static table. When the `dynamic-loading` feature is enabled, falls back to loading a shared library on demand. **Errors:** Returns `Error.LanguageNotFound` if the name (after alias resolution) does not match any known grammar. **Signature:** ```swift public func getLanguage(name: String) throws -> Language ``` **Example:** ```swift let result = try instance.getLanguage("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Language` **Errors:** Throws `Error`. ###### availableLanguages() [Section titled “availableLanguages()”](#availablelanguages-1) List all available language names, sorted and deduplicated. Includes statically compiled languages, dynamically loadable languages (if the `dynamic-loading` feature is enabled), and all configured aliases. **Signature:** ```swift public func availableLanguages() -> [String] ``` **Example:** ```swift let result = instance.availableLanguages() ``` **Returns:** `[String]` ###### hasParser() [Section titled “hasParser()”](#hasparser) Check whether this language can be parsed right now, without downloading. Resolves aliases, then answers from exactly the lookup `get_language` performs: the statically compiled table, the already-loaded dynamic grammars, and the parser shared libraries present in the primary and extra (download-cache) library directories. It never performs network I/O. A previous implementation consulted only the statically compiled table. That table is empty in every build that does not set `TSLP_LANGUAGES`, so the function answered `false` for languages this registry parses perfectly well. Contrast `has_language`, which is also `true` for a grammar that is merely *known to the manifest* and would have to be downloaded first. The pair distinguishes “we can parse it offline, now” from “we recognise the name”. The first `true` answer for a dynamic grammar loads its shared library: loading is the only way to know the grammar is usable, since a truncated or wrong-architecture library exists on disk but cannot parse. Loads are cached process-wide, so repeat calls are cheap. **Signature:** ```swift public func hasParser(name: String) -> Bool ``` **Example:** ```swift let result = instance.hasParser("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Bool` ###### hasLanguage() [Section titled “hasLanguage()”](#haslanguage-1) Check whether a language is available by name or alias. Returns `true` if the language can be loaded, either from the static table or from a dynamic library on disk. Every branch is one more way to answer `true`, so they are ordered cheapest-first and the filesystem is only consulted once every in-memory source has said no. Probing the loaded-grammar map and the manifest ahead of the `stat` calls is what keeps this off the syscall path for the languages a process actually uses. **Signature:** ```swift public func hasLanguage(name: String) -> Bool ``` **Example:** ```swift let result = instance.hasLanguage("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Bool` ###### languageCount() [Section titled “languageCount()”](#languagecount-1) Return the total number of available languages (including aliases). Counts the same set `available_languages` lists, without materialising or sorting it. **Signature:** ```swift public func languageCount() -> UInt ``` **Example:** ```swift let result = instance.languageCount() ``` **Returns:** `UInt` ###### process() [Section titled “process()”](#process-1) Parse source code and extract file intelligence based on config in a single pass. **Errors:** Returns `Error.InvalidRange` if the config is invalid (see `ProcessConfig.validate`) or if the source exceeds the configured `max_source_bytes`; `Error.LanguageNotFound` if the language is unknown; or `Error.ParseFailed` if parsing produces no tree. **Signature:** ```swift public func process(source: String, config: ProcessConfig) throws -> ProcessResult ``` **Example:** ```swift let result = try instance.process("value", ProcessConfig()) ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `String` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Throws `Error`. *** #### Node [Section titled “Node”](#node) A single syntax node within a `Tree`. Nodes hold a strong reference to their parent tree so they remain valid regardless of how the tree is moved or stored at the FFI boundary. ##### Methods [Section titled “Methods”](#methods-2) ###### kind() [Section titled “kind()”](#kind) Return the node’s kind name (e.g. `"function_definition"`). **Signature:** ```swift public func kind() -> String ``` **Example:** ```swift let result = instance.kind() ``` **Returns:** `String` ###### kindId() [Section titled “kindId()”](#kindid) Return the node’s numeric kind ID. Tree-sitter assigns a stable `u16` ID to every node kind in a grammar (e.g. `"function_definition" → 42`). Comparing `kind_id()` is cheaper than comparing the string `kind()` in tight AST loops. **Signature:** ```swift public func kindId() -> UInt16 ``` **Example:** ```swift let result = instance.kindId() ``` **Returns:** `UInt16` ###### startByte() [Section titled “startByte()”](#startbyte) Return the inclusive start byte offset of this node. **Signature:** ```swift public func startByte() -> UInt ``` **Example:** ```swift let result = instance.startByte() ``` **Returns:** `UInt` ###### endByte() [Section titled “endByte()”](#endbyte) Return the exclusive end byte offset of this node. **Signature:** ```swift public func endByte() -> UInt ``` **Example:** ```swift let result = instance.endByte() ``` **Returns:** `UInt` ###### byteRange() [Section titled “byteRange()”](#byterange-1) Return the node’s byte range as a `ByteRange`. Callers should slice their own source bytes — this is a zero-copy text accessor. **Signature:** ```swift public func byteRange() -> ByteRange ``` **Example:** ```swift let result = instance.byteRange() ``` **Returns:** `ByteRange` ###### startPosition() [Section titled “startPosition()”](#startposition) Return the start `Point` (row, column). **Signature:** ```swift public func startPosition() -> Point ``` **Example:** ```swift let result = instance.startPosition() ``` **Returns:** `Point` ###### endPosition() [Section titled “endPosition()”](#endposition) Return the end `Point` (row, column). **Signature:** ```swift public func endPosition() -> Point ``` **Example:** ```swift let result = instance.endPosition() ``` **Returns:** `Point` ###### isNamed() [Section titled “isNamed()”](#isnamed) True when this node is named (not punctuation/whitespace). **Signature:** ```swift public func isNamed() -> Bool ``` **Example:** ```swift let result = instance.isNamed() ``` **Returns:** `Bool` ###### isError() [Section titled “isError()”](#iserror) True when this is an error node. **Signature:** ```swift public func isError() -> Bool ``` **Example:** ```swift let result = instance.isError() ``` **Returns:** `Bool` ###### isMissing() [Section titled “isMissing()”](#ismissing) True when this is a missing-token node. **Signature:** ```swift public func isMissing() -> Bool ``` **Example:** ```swift let result = instance.isMissing() ``` **Returns:** `Bool` ###### isExtra() [Section titled “isExtra()”](#isextra) True when this is an “extra” node (e.g. a comment). **Signature:** ```swift public func isExtra() -> Bool ``` **Example:** ```swift let result = instance.isExtra() ``` **Returns:** `Bool` ###### hasError() [Section titled “hasError()”](#haserror) True when this node or any descendant is an error. **Signature:** ```swift public func hasError() -> Bool ``` **Example:** ```swift let result = instance.hasError() ``` **Returns:** `Bool` ###### parent() [Section titled “parent()”](#parent) Return this node’s parent, if any. **Signature:** ```swift public func parent() -> Node? ``` **Example:** ```swift let result = instance.parent() ``` **Returns:** `Node?` ###### child() [Section titled “child()”](#child) Return the i-th child of this node, if any. **Signature:** ```swift public func child(index: UInt32) -> Node? ``` **Example:** ```swift let result = instance.child(42) ``` **Parameters:** | Name | Type | Required | Description | | ------- | -------- | -------- | ----------- | | `index` | `UInt32` | Yes | The index | **Returns:** `Node?` ###### childCount() [Section titled “childCount()”](#childcount) Total number of children (including unnamed). **Signature:** ```swift public func childCount() -> UInt ``` **Example:** ```swift let result = instance.childCount() ``` **Returns:** `UInt` ###### namedChild() [Section titled “namedChild()”](#namedchild) Return the i-th named child of this node, if any. **Signature:** ```swift public func namedChild(index: UInt32) -> Node? ``` **Example:** ```swift let result = instance.namedChild(42) ``` **Parameters:** | Name | Type | Required | Description | | ------- | -------- | -------- | ----------- | | `index` | `UInt32` | Yes | The index | **Returns:** `Node?` ###### namedChildCount() [Section titled “namedChildCount()”](#namedchildcount) Number of named children of this node. **Signature:** ```swift public func namedChildCount() -> UInt ``` **Example:** ```swift let result = instance.namedChildCount() ``` **Returns:** `UInt` ###### childByFieldName() [Section titled “childByFieldName()”](#childbyfieldname) Look up a child by its grammar-defined field name. **Signature:** ```swift public func childByFieldName(name: String) -> Node? ``` **Example:** ```swift let result = instance.childByFieldName("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** `Node?` ###### toSexp() [Section titled “toSexp()”](#tosexp) Return the S-expression form of this node’s subtree. **Signature:** ```swift public func toSexp() -> String ``` **Example:** ```swift let result = instance.toSexp() ``` **Returns:** `String` ###### walk() [Section titled “walk()”](#walk) Return a `TreeCursor` positioned at this node. **Signature:** ```swift public func walk() -> TreeCursor ``` **Example:** ```swift let result = instance.walk() ``` **Returns:** `TreeCursor` *** #### PackConfig [Section titled “PackConfig”](#packconfig) Configuration for the tree-sitter language pack. Controls cache directory and which languages to pre-download. Can be loaded from a TOML file, constructed programmatically, or passed as a dict/object from language bindings. | Field | Type | Default | Description | | ----------- | ------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cacheDir` | `URL?` | `null` | Override the BASE directory the parser cache lives under. This is a base, not the final library path: the crate appends `tree-sitter-language-pack/v{version}/libs` to it, exactly as it does to the platform default. So `cache_dir = "/tmp/my-parsers"` resolves to `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`. The suffix is not cosmetic. It keeps the whole cache tree — manifest, bundles and lock file included — inside a directory this library owns and versions. Earlier releases used this path verbatim, which put those files in the configured directory’s PARENT and let a cache built by one crate version be reused by another. Default base: the platform cache dir, e.g. `~/.cache` on Linux. | | `languages` | `\[String\]?` | `[]` | Languages to pre-download on init. Each entry is a language name (e.g. `"python"`, `"rust"`). | | `groups` | `\[String\]?` | `[]` | Language groups to pre-download. Group names come from the remote manifest, so the valid set is not fixed by this library; the published manifest currently defines only `"all"`. Call `manifest_groups` to enumerate them. An unknown name makes `init` fail. | *** #### Parser [Section titled “Parser”](#parser) A tree-sitter parser configured for one language at a time. ##### Methods [Section titled “Methods”](#methods-3) ###### new() [Section titled “new()”](#new-2) Construct a new parser with no language set and no parse limits. Call `Parser.set_language` before parsing. Limits are opt-in via `set_max_source_bytes` and `set_parse_timeout_ms`; both default to unbounded so that existing callers are unaffected. **Signature:** ```swift public init() ``` **Example:** ```swift let result = Parser.new() ``` **Returns:** `Parser` ###### setMaxSourceBytes() [Section titled “setMaxSourceBytes()”](#setmaxsourcebytes) Refuse to parse sources longer than `max_bytes`. `null` (the default) means no limit. Over-limit input makes `parse` and `parse_bytes` return `null` after emitting a `WARN`; input is never silently truncated. See `RECOMMENDED_MAX_SOURCE_BYTES`. **Signature:** ```swift public func setMaxSourceBytes(maxBytes: UInt? = nil) ``` **Example:** ```swift instance.setMaxSourceBytes(42) ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ------- | -------- | ------------- | | `maxBytes` | `UInt?` | No | The max bytes | **Returns:** No return value. ###### setParseTimeoutMs() [Section titled “setParseTimeoutMs()”](#setparsetimeoutms) Cancel a parse that exceeds `timeout_ms` milliseconds of wall clock. `null` (the default) means no budget. Cancellation runs through tree-sitter’s parse progress callback, so it is granular to that callback’s interval rather than exact. See `RECOMMENDED_PARSE_TIMEOUT_MS`. **Signature:** ```swift public func setParseTimeoutMs(timeoutMs: UInt64? = nil) ``` **Example:** ```swift instance.setParseTimeoutMs(42) ``` **Parameters:** | Name | Type | Required | Description | | ----------- | --------- | -------- | -------------- | | `timeoutMs` | `UInt64?` | No | The timeout ms | **Returns:** No return value. ###### setLanguage() [Section titled “setLanguage()”](#setlanguage) Configure the parser to use the language identified by name (e.g. `"python"`). Resolves the language through the global registry — auto-downloading if necessary, when the `download` feature is enabled. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language ABI is incompatible. **Signature:** ```swift public func setLanguage(name: String) throws ``` **Example:** ```swift try instance.setLanguage("value") ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `String` | Yes | The name | **Returns:** No return value. **Errors:** Throws `Error`. ###### parse() [Section titled “parse()”](#parse) Parse a UTF-8 source string. Returns `null` if no language is set, if the parse was cancelled by the configured timeout, or if the source exceeds the configured size limit. Each non-parse outcome is logged, so an empty result is never silent. ###### Concurrency [Section titled “Concurrency”](#concurrency) Parsing runs fully in parallel across threads for almost every language — no lock is taken. The exception is the small set of grammars whose external scanner keeps mutable process-global state (currently just `properties`): parses of that language are serialized against each other through an internal per-language lock, so that concurrent threads can’t corrupt shared scanner state. Every other language is unaffected by that lock and never waits on it. **Signature:** ```swift public func parse(source: String) -> Tree? ``` **Example:** ```swift let result = instance.parse("value") ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------- | -------- | ----------- | | `source` | `String` | Yes | The source | **Returns:** `Tree?` ###### parseBytes() [Section titled “parseBytes()”](#parsebytes) Parse a raw byte slice. Same outcomes as `parse`, including the concurrency behaviour documented there. **Signature:** ```swift public func parseBytes(source: Data) -> Tree? ``` **Example:** ```swift let result = instance.parseBytes(Data("data".utf8)) ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------ | -------- | ----------- | | `source` | `Data` | Yes | The source | **Returns:** `Tree?` ###### reset() [Section titled “reset()”](#reset) Reset internal state. The next call to `parse` will not be incremental. **Signature:** ```swift public func reset() ``` **Example:** ```swift instance.reset() ``` **Returns:** No return value. *** #### Point [Section titled “Point”](#point) A source position — row + column, zero-indexed. | Field | Type | Default | Description | | -------- | ------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `row` | `UInt` | — | Zero-indexed row number. | | `column` | `UInt` | — | Zero-indexed column, counted in **bytes** from the start of the row. This is `tree_sitter.Point.column` verbatim, and tree-sitter defines it as a byte offset — not characters, and not UTF-16 code units. Measured on a row of the form `x = ''` where `` is a single 4-byte character (an emoji), the string node reports columns `4..10`, identical to its byte range; the character columns would be `4..7` and the UTF-16 columns `4..8`. Anything that builds LSP positions (UTF-16) or editor caret columns (characters) from this field is silently wrong on every row containing a non-ASCII byte, and must re-measure the row against the source text instead. Earlier releases documented this field as UTF-16 code units; that was never what the value contained. | *** #### ProcessConfig [Section titled “ProcessConfig”](#processconfig) Configuration for the `process()` function. Controls which analysis features are enabled and whether chunking is performed. | Field | Type | Default | Description | | ---------------- | --------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String` | `""` | Language name (required). | | `structure` | `Bool` | `true` | Extract structural items (functions, classes, etc.). Default: true. | | `imports` | `Bool` | `true` | Extract import statements. Default: true. | | `exports` | `Bool` | `true` | Extract export statements. Default: true. | | `comments` | `Bool` | `false` | Extract comments. Default: false. | | `docstrings` | `Bool` | `false` | Extract docstrings. Default: false. | | `symbols` | `Bool` | `false` | Extract symbol definitions. Default: false. | | `diagnostics` | `Bool` | `false` | Include parse diagnostics. Default: false. | | `chunkMaxSize` | `UInt?` | `null` | Maximum chunk size in bytes. `null` disables chunking. `Some(0)` is rejected by `ProcessConfig.validate` with `Error.InvalidRange`. A zero-sized chunk limit previously produced an empty chunk list and silently discarded the whole source; use `null` to mean “do not chunk”. | | `dataExtraction` | `Bool` | `false` | Extract hierarchical key/value data tree from data-format files. Default: false. When `true`, `ProcessResult.data` is populated with a `DataNode` tree for supported languages: JSON, YAML, TOML, `.properties`, HCL/HOCON, INI, editorconfig, KDL, CUE, CSV, PSV, PO, nginx config, Caddy config, XML, and DTD. For languages outside this set the field is left as `null`. | | `maxSourceBytes` | `UInt?` | `null` | Reject source longer than this many bytes instead of parsing it. Default: `null` (unbounded). Tree-sitter allocates and walks proportionally to input size, so an unbounded parse of attacker-supplied input is a denial-of-service vector. The default stays unbounded for backward compatibility; services handling untrusted input should opt in, e.g. with `RECOMMENDED_MAX_SOURCE_BYTES`. Exceeding the limit fails the call with `Error.InvalidRange` — the source is never silently truncated. | | `parseTimeoutMs` | `UInt64?` | `null` | Wall-clock budget for the parse step, in milliseconds. Default: `null` (no timeout). Enforced through tree-sitter’s parse progress callback, which the parser invokes periodically; cancellation is therefore granular to that callback interval rather than exact. A parse that exceeds the budget fails with `Error.ParseTimeout`. | *** #### ProcessResult [Section titled “ProcessResult”](#processresult) Complete analysis result from processing a source file. Contains metrics, structural analysis, imports/exports, comments, docstrings, symbols, diagnostics, and optionally chunked code segments. Fields are populated based on the `ProcessConfig` flags. | Field | Type | Default | Description | | ------------- | ------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String` | — | The language name used to parse the source file. | | `metrics` | `FileMetrics` | — | File-level metrics (line counts, byte size, error count). | | `structure` | `\[StructureItem\]` | `[]` | Top-level structural items (functions, classes, etc.). | | `imports` | `\[ImportInfo\]` | `[]` | Import statements extracted from the source. | | `exports` | `\[ExportInfo\]` | `[]` | Export statements extracted from the source. | | `comments` | `\[CommentInfo\]` | `[]` | Comments extracted from the source. | | `docstrings` | `\[DocstringInfo\]` | `[]` | Docstrings extracted from the source. | | `symbols` | `\[SymbolInfo\]` | `[]` | Symbol definitions (variables, types, functions) extracted from the source. | | `diagnostics` | `\[Diagnostic\]` | `[]` | Parse diagnostics (syntax errors, missing nodes) from tree-sitter. | | `chunks` | `\[CodeChunk\]` | `[]` | Syntax-aware code chunks produced when chunking is enabled. | | `data` | `DataNode?` | `null` | Hierarchical data tree extracted when `config.data_extraction` is `true`. Populated for supported data-format languages (JSON, YAML, TOML, properties, HCL, INI, XML, CSV, and more). `null` when `data_extraction` is `false` (the default) or when the language is not a recognised data format. See `DataNode` for the shape of the returned tree. | *** #### Span [Section titled “Span”](#span) Byte and line/column range in source code. Represents both byte offsets (for slicing) and human-readable line/column positions (for display and diagnostics). | Field | Type | Default | Description | | ------------- | ------ | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `startByte` | `UInt` | — | Inclusive start byte offset in the source. | | `endByte` | `UInt` | — | Exclusive end byte offset in the source. | | `startLine` | `UInt` | — | Zero-indexed line number of the span’s start. | | `startColumn` | `UInt` | — | Zero-indexed column of the span’s start, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | | `endLine` | `UInt` | — | Zero-indexed line number of the span’s end. | | `endColumn` | `UInt` | — | Zero-indexed column of the span’s end, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | *** #### StructureItem [Section titled “StructureItem”](#structureitem) A structural item (function, class, struct, etc.) in source code. | Field | Type | Default | Description | | ------------ | ------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `kind` | `StructureKind` | `StructureKind.function` | The kind of structural item. | | `name` | `String?` | `null` | The declared name of the item, if present. | | `visibility` | `String?` | `null` | Visibility modifier (e.g., `"pub"`, `"public"`, `"private"`). | | `span` | `Span` | — | Source span covering the entire item declaration. | | `children` | `\[StructureItem\]` | `[]` | Nested structural items (e.g., methods within a class). | | `decorators` | `\[String\]` | `[]` | Decorator or attribute names applied to the item. **Reserved: not yet populated.** Always empty, for every language. Recognising a decorator requires per-language grammar knowledge (a Python `decorated_definition` wrapper, Java/C# annotations, Rust attributes each have a different shape), which no extractor here implements yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | | `docComment` | `String?` | `null` | Documentation comment attached to the item, if any. The text of the comment (or run of comments) immediately preceding the item, with no blank line in between, when that comment is classified as a doc comment. Multiple adjacent single-line doc comments (Rust `///`) are joined with `\n` in source order. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`). `null` for every other language, and for a preceding comment that is not in doc-comment form (a plain `#` comment in Python, Ruby, or Elixir) — Python’s docstring convention is captured separately, as `DocstringInfo`, not through this field. | | `signature` | `String?` | `null` | Full signature text of the item (e.g., function parameters and return type). The item’s own source text from its start up to the start of its body (see `StructureItem.body_span`), trimmed of trailing whitespace — for example `fn add(a: i32, b: i32) -> i32` for a Rust function whose body is `{ a + b }`. `null` only when that text is empty, which does not happen for any item `StructureKind` currently reports. Populated for every language and kind this library extracts structure for, since it is derived from `body_span`’s boundary rather than per-language syntax. | | `bodySpan` | `Span?` | `null` | Source span covering only the body of the item, if distinct from the declaration. | *** #### SymbolInfo [Section titled “SymbolInfo”](#symbolinfo) A symbol (variable, function, type, etc.) extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------ | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `String` | — | The name of the symbol. | | `kind` | `SymbolKind` | `SymbolKind.variable` | The kind of symbol (variable, function, class, etc.). | | `span` | `Span` | — | Source span covering the symbol definition. | | `typeAnnotation` | `String?` | `null` | Explicit type annotation, if present in the source. | | `doc` | `String?` | `null` | Documentation comment immediately preceding this symbol, resolved by the same walk `StructureItem.doc_comment` uses (see `doc_comment_at`) — never hard-coded `null`. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`) — the languages whose comment classification recognizes a doc-kind comment. `null` for every other language (e.g. Python, Go, Ruby, which have no doc-kind comment classification), and also `null` when a symbol in a supported language simply has no doc comment immediately above it. | *** #### Tree [Section titled “Tree”](#tree) A parsed syntax tree. Cheap to clone (refcount bump). ##### Methods [Section titled “Methods”](#methods-4) ###### rootNode() [Section titled “rootNode()”](#rootnode) Return the root `Node` of this tree. **Signature:** ```swift public func rootNode() -> Node ``` **Example:** ```swift let result = instance.rootNode() ``` **Returns:** `Node` ###### walk() [Section titled “walk()”](#walk-1) Return a `TreeCursor` positioned at the root. **Signature:** ```swift public func walk() -> TreeCursor ``` **Example:** ```swift let result = instance.walk() ``` **Returns:** `TreeCursor` *** #### TreeCursor [Section titled “TreeCursor”](#treecursor) A cursor for traversing a `Tree`. ##### Methods [Section titled “Methods”](#methods-5) ###### node() [Section titled “node()”](#node-1) Return the `Node` at the cursor’s current position. **Signature:** ```swift public func node() -> Node ``` **Example:** ```swift let result = instance.node() ``` **Returns:** `Node` ###### gotoFirstChild() [Section titled “gotoFirstChild()”](#gotofirstchild) Move the cursor to the first child of the current node. Returns `true` if a child existed. **Signature:** ```swift public func gotoFirstChild() -> Bool ``` **Example:** ```swift let result = instance.gotoFirstChild() ``` **Returns:** `Bool` ###### gotoParent() [Section titled “gotoParent()”](#gotoparent) Move the cursor to the parent of the current node. Returns `true` if a parent existed. **Signature:** ```swift public func gotoParent() -> Bool ``` **Example:** ```swift let result = instance.gotoParent() ``` **Returns:** `Bool` ###### gotoNextSibling() [Section titled “gotoNextSibling()”](#gotonextsibling) Move the cursor to the next sibling of the current node. Returns `true` if a sibling existed. **Signature:** ```swift public func gotoNextSibling() -> Bool ``` **Example:** ```swift let result = instance.gotoNextSibling() ``` **Returns:** `Bool` ###### fieldName() [Section titled “fieldName()”](#fieldname) Return the field name for the current node, if any. **Signature:** ```swift public func fieldName() -> String? ``` **Example:** ```swift let result = instance.fieldName() ``` **Returns:** `String?` *** ### Enums [Section titled “Enums”](#enums) #### DataNodeKind [Section titled “DataNodeKind”](#datanodekind) The kind of a data node extracted from a data-format file. Classifies each node in the hierarchical `DataNode` tree returned when `data_extraction` is enabled on `ProcessConfig`. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract) Unit variants serialize as a bare string (`"KeyValue"`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ---------- | -------------------------------------------------------------------------------------------------------------------- | | `KeyValue` | A key/value pair or mapping (json/toml/properties/yaml/hcl/cue/kdl pair, or a wrapper “object”/“mapping” container). | | `Element` | An XML element with a tag name in `key` and attributes in `attributes`. | | `Sequence` | A positional sequence item (JSON array element, YAML block sequence item, CSV/PSV row or cell). | *** #### StructureKind [Section titled “StructureKind”](#structurekind) The kind of structural item found in source code. Categorizes top-level and nested declarations such as functions, classes, structs, enums, traits, and more. Use `Other` for language-specific constructs that do not fit a standard category. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-1) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | ---------------------------------------------------------------------------------------------- | | `Function` | A free-standing or associated function. | | `Method` | A method defined inside a class, struct, trait, or impl block. | | `Class` | A class definition. | | `Struct` | A struct definition. | | `Interface` | An interface or protocol definition. | | `Enum` | An enum definition. | | `Module` | A module or package declaration. | | `Trait` | A trait definition. | | `Impl` | An impl block (Rust) or similar implementation block. | | `Namespace` | A namespace declaration. | | `Other` | A language-specific construct that does not fit any standard category. — Fields: `0`: `String` | *** #### CommentKind [Section titled “CommentKind”](#commentkind) The kind of a comment found in source code. Distinguishes between single-line comments, block (multi-line) comments, and documentation comments. | Value | Description | | ------- | --------------------------------------------------------------------- | | `Line` | A single-line comment (e.g., `// ...` or `# ...`). | | `Block` | A block or multi-line comment using slash-star delimiters. | | `Doc` | A documentation comment such as `/// ...` or slash-double-star block. | *** #### DocstringFormat [Section titled “DocstringFormat”](#docstringformat) The format of a docstring extracted from source code. Identifies the docstring convention used, which varies by language (e.g., Python triple-quoted strings, JSDoc, Rustdoc `///` comments). ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-2) Unit variants serialize as a bare string (`"JSDoc"`); the `Other` variant serializes as a single-keyed object (`{"Other": "rst"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ------------------- | -------------------------------------------------------------------------------------------------- | | `PythonTripleQuote` | Python triple-quoted string docstring (`"""..."""`). | | `JsDoc` | JavaScript/TypeScript JSDoc block comment (opens with two stars, closes with star-slash). | | `Rustdoc` | Rust `///` or `//!` doc comment. | | `GoDoc` | Go doc comment (a comment block immediately preceding a declaration). | | `JavaDoc` | Java Javadoc block comment (opens with two stars, closes with star-slash). | | `Other` | A language-specific docstring format not covered by the standard variants. — Fields: `0`: `String` | *** #### ExportKind [Section titled “ExportKind”](#exportkind) The kind of an export statement found in source code. Covers named exports, default exports, and re-exports from other modules. | Value | Description | | ---------- | -------------------------------------------------------------------- | | `Named` | A named export (e.g., `export { foo }`). | | `Default` | A default export (e.g., `export default foo`). | | `ReExport` | A re-export from another module (e.g., `export { foo } from 'bar'`). | *** #### SymbolKind [Section titled “SymbolKind”](#symbolkind) The kind of a symbol definition found in source code. Categorizes symbol definitions such as variables, constants, functions, classes, types, interfaces, enums, and modules. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-3) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | --------------------------------------------------------------------------- | | `Variable` | A variable binding. | | `Constant` | A constant (immutable binding). | | `Function` | A function definition. | | `Class` | A class definition. | | `Type` | A type alias or typedef. | | `Interface` | An interface definition. | | `Enum` | An enum definition. | | `Module` | A module declaration. | | `Other` | A symbol kind not covered by the standard variants. — Fields: `0`: `String` | *** #### DiagnosticSeverity [Section titled “DiagnosticSeverity”](#diagnosticseverity) Severity level of a diagnostic produced during parsing. Used to classify parse errors, warnings, and informational messages found in the syntax tree. | Value | Description | | --------- | --------------------------------------------------------------- | | `Error` | A parse error (e.g., an `ERROR` or `MISSING` node in the tree). | | `Warning` | A warning-level diagnostic. | | `Info` | An informational diagnostic. | *** ### Errors [Section titled “Errors”](#errors) #### Error [Section titled “Error”](#error) Errors that can occur when using the tree-sitter language pack. Covers language lookup failures, parse errors, query errors, and I/O issues. Feature-gated variants are included when `config`, `download`, or related features are enabled. ##### Matching on `Error` [Section titled “Matching on Error”](#matching-on-error) The set of variants is not stable: new failure modes are added in minor releases, and `Io`, `Json`, and `Toml` exist only under certain feature combinations, so the variant set a downstream crate sees depends on which features it enables. Downstream `match`es must therefore carry a `_` arm; `#[non_exhaustive]` makes the compiler enforce that instead of letting a feature change silently break a build. ##### C ABI error codes [Section titled “C ABI error codes”](#c-abi-error-codes) Each variant alef can see carries an explicit `alef(error_code = N)` allocation that becomes a member of the generated `AlefFfiErrorCode` C enum. These numbers are a public ABI contract: **an allocated number is never reused after its variant is removed**, and a variant’s number never changes, because C callers compare against the value, not the name. New variants take the next free number. 0-4 are reserved by alef, so allocation starts at 100. An unannotated variant is emitted as the unknown code rather than as itself, which silently flattens the taxonomy — annotate every new variant. | Variant | Description | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `languageNotFound` | The requested language name (or alias) was not found in the registry. | | `dynamicLoad` | A dynamic shared library could not be loaded at runtime. | | `nullLanguagePointer` | The tree-sitter language function returned a null pointer for the given language name. | | `parserSetup` | The language could not be applied to the parser (e.g., ABI version mismatch). | | `lockPoisoned` | An internal `RwLock` or `Mutex` was poisoned by a previous panic. | | `config` | A configuration file or value was invalid or could not be applied. | | `parseFailed` | The tree-sitter parser returned no tree for the given source input. | | `parseTimeout` | The parse was cancelled because it exceeded its configured wall-clock budget. Raised only when a budget is configured — see `ProcessConfig.parse_timeout_ms`, which defaults to `null`. | | `queryError` | A tree-sitter query could not be compiled or executed. | | `invalidRange` | A byte range was invalid (e.g., end before start, or out of bounds). | | `download` | A parser download from GitHub releases failed. | | `checksumMismatch` | The downloaded file’s SHA-256 digest did not match the manifest’s expected value. | | `cacheLock` | The cross-process download cache lock file could not be acquired or created. | *** # TypeScript API Reference ## TypeScript API Reference v1.16.1 [Section titled “TypeScript API Reference v1.16.1”](#typescript-api-reference-v1161) ### Functions [Section titled “Functions”](#functions) #### detectLanguageFromExtension() [Section titled “detectLanguageFromExtension()”](#detectlanguagefromextension) Detect language name from a file extension (without leading dot). Returns `null` for unrecognized extensions. The match is case-insensitive. **Signature:** ```typescript function detectLanguageFromExtension(ext: string): string | null ``` **Example:** ```typescript const result = detectLanguageFromExtension("value"); ``` **Parameters:** | Name | Type | Required | Description | | ----- | -------- | -------- | ----------- | | `ext` | `string` | Yes | The ext | **Returns:** `string | null` *** #### detectLanguageFromPath() [Section titled “detectLanguageFromPath()”](#detectlanguagefrompath) Detect language name from a file path. Extracts the file extension and looks it up. Returns `null` if the path has no extension or the extension is not recognized. **Signature:** ```typescript function detectLanguageFromPath(path: string): string | null ``` **Example:** ```typescript const result = detectLanguageFromPath("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `path` | `string` | Yes | Path to the file | **Returns:** `string | null` *** #### detectLanguageFromContent() [Section titled “detectLanguageFromContent()”](#detectlanguagefromcontent) Detect language name from file content using the shebang line (`#!`). Inspects only the first line of `content`. If it begins with `#!`, the interpreter name is extracted and mapped to a language name. Handles common patterns: * `#!/usr/bin/env python3` → `"python"` * `#!/bin/bash` → `"bash"` * `#!/usr/bin/env node` → `"javascript"` The `-S` flag accepted by some `env` implementations is skipped automatically. Version suffixes (e.g. `python3.11`, `ruby3.2`) are stripped before matching. A leading UTF-8 BOM (`U+FEFF`) is skipped before the `#!` check, so a BOM-prefixed script is still detected by its shebang. Returns `null` when content does not start with `#!` (after stripping a leading BOM), the shebang is malformed, or the interpreter is not recognised. **Signature:** ```typescript function detectLanguageFromContent(content: string): string | null ``` **Example:** ```typescript const result = detectLanguageFromContent("value"); ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ---------------------- | | `content` | `string` | Yes | The content to process | **Returns:** `string | null` *** #### getHighlightsQuery() [Section titled “getHighlightsQuery()”](#gethighlightsquery) Get the highlights query for a language, if bundled. Returns the contents of `highlights.scm` as a static string, or `null` if no highlights query is bundled for this language. **Signature:** ```typescript function getHighlightsQuery(language: string): string | null ``` **Example:** ```typescript const result = getHighlightsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `string | null` *** #### getInjectionsQuery() [Section titled “getInjectionsQuery()”](#getinjectionsquery) Get the injections query for a language, if bundled. Returns the contents of `injections.scm` as a static string, or `null` if no injections query is bundled for this language. **Signature:** ```typescript function getInjectionsQuery(language: string): string | null ``` **Example:** ```typescript const result = getInjectionsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `string | null` *** #### getLocalsQuery() [Section titled “getLocalsQuery()”](#getlocalsquery) Get the locals query for a language, if bundled. Returns the contents of `locals.scm` as a static string, or `null` if no locals query is bundled for this language. **Signature:** ```typescript function getLocalsQuery(language: string): string | null ``` **Example:** ```typescript const result = getLocalsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `string | null` *** #### getTagsQuery() [Section titled “getTagsQuery()”](#gettagsquery) Get the tags query for a language, if bundled. Returns the contents of `tags.scm` as a static string, or `null` if no tags query is bundled for this language. **Signature:** ```typescript function getTagsQuery(language: string): string | null ``` **Example:** ```typescript const result = getTagsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `string | null` *** #### getIndentsQuery() [Section titled “getIndentsQuery()”](#getindentsquery) Get the indents query for a language, if bundled. Returns the contents of `indents.scm` (used for auto-indentation) as a static string, or `null` if no indents query is bundled for this language. **Signature:** ```typescript function getIndentsQuery(language: string): string | null ``` **Example:** ```typescript const result = getIndentsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `string | null` *** #### getFoldsQuery() [Section titled “getFoldsQuery()”](#getfoldsquery) Get the folds query for a language, if bundled. Returns the contents of `folds.scm` (used for code folding) as a static string, or `null` if no folds query is bundled for this language. **Signature:** ```typescript function getFoldsQuery(language: string): string | null ``` **Example:** ```typescript const result = getFoldsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `string | null` *** #### getLanguage() [Section titled “getLanguage()”](#getlanguage) Get a tree-sitter `Language` by name using the global registry. Resolves language aliases (e.g., `"shell"` maps to `"bash"`). When the `download` feature is enabled (default), automatically downloads the parser from GitHub releases if not found locally. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.Download` if auto-download fails. **Signature:** ```typescript function getLanguage(name: string): Language ``` **Example:** ```typescript const result = getLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `Language` **Errors:** Throws `Error` with a descriptive message. *** #### getParser() [Section titled “getParser()”](#getparser) Get a `Parser` pre-configured for the given language. This is a convenience function that calls `get_language` and configures a new parser in one step. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language cannot be applied to the parser. **Signature:** ```typescript function getParser(name: string): Parser ``` **Example:** ```typescript const result = getParser("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `Parser` **Errors:** Throws `Error` with a descriptive message. *** #### detectLanguage() [Section titled “detectLanguage()”](#detectlanguage) Detect language name from a file path or extension. This compatibility alias matches the pre-Alef Python binding API. **Signature:** ```typescript function detectLanguage(path: string): string | null ``` **Example:** ```typescript const result = detectLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `path` | `string` | Yes | Path to the file | **Returns:** `string | null` *** #### availableLanguages() [Section titled “availableLanguages()”](#availablelanguages) List all available language names (sorted, deduplicated, includes aliases). Returns names of both statically compiled and dynamically loadable languages, plus any configured aliases. **Signature:** ```typescript function availableLanguages(): Array ``` **Example:** ```typescript const result = availableLanguages(); ``` **Returns:** `Array` *** #### hasLanguage() [Section titled “hasLanguage()”](#haslanguage) Check if a language is available by name or alias. Returns `true` if the language can be loaded (statically compiled, dynamically available, or a known alias for one of these). **Signature:** ```typescript function hasLanguage(name: string): boolean ``` **Example:** ```typescript const result = hasLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `boolean` *** #### languageCount() [Section titled “languageCount()”](#languagecount) Return the number of available languages. Includes statically compiled languages, dynamically loadable languages, and aliases. **Signature:** ```typescript function languageCount(): number ``` **Example:** ```typescript const result = languageCount(); ``` **Returns:** `number` *** #### process() [Section titled “process()”](#process) Process source code and extract file intelligence using the global registry. Parses the source with tree-sitter and extracts metrics, structure, imports, exports, comments, docstrings, symbols, diagnostics, and/or chunks based on the flags set in `ProcessConfig`. **Errors:** Returns `Error.InvalidRange` if the config carries a zero-valued limit or the source exceeds `ProcessConfig.max_source_bytes`, `Error.ParseTimeout` if the parse exceeds `ProcessConfig.parse_timeout_ms`, `Error.LanguageNotFound` if the language is unknown, or `Error.ParseFailed` if parsing yields no tree. **Signature:** ```typescript function process(source: string, config: ProcessConfig): ProcessResult ``` **Example:** ```typescript const result = process("value", new ProcessConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `string` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Throws `Error` with a descriptive message. *** #### init() [Section titled “init()”](#init) Initialize the language pack with the given configuration. Applies any custom cache directory, then downloads all languages and groups specified in the config. This is the recommended entry point when you want to pre-warm the cache before use. **Errors:** Returns an error if configuration cannot be applied or if downloads fail. **Signature:** ```typescript function init(config: PackConfig): void ``` **Example:** ```typescript init(new PackConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Throws `Error` with a descriptive message. *** #### configure() [Section titled “configure()”](#configure) Apply download configuration without downloading anything. Use this to set a custom cache directory before the first call to `get_language` or any download function. Changing the cache dir after languages have been registered has no effect on already-loaded languages. `PackConfig.cache_dir` is a BASE directory, not the final libs path: this crate appends `tree-sitter-language-pack/v{version}/libs` to it, the same suffix applied to the platform default cache directory. In the example below, files actually land under `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`, never directly in `/tmp/my-parsers/`. Call `cache_dir` to read back the resolved, fully-suffixed path. **Errors:** Returns an error if the lock cannot be acquired. **Signature:** ```typescript function configure(config: PackConfig): void ``` **Example:** ```typescript configure(new PackConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | ------------ | -------- | ------------------------- | | `config` | `PackConfig` | Yes | The configuration options | **Returns:** No return value. **Errors:** Throws `Error` with a descriptive message. *** #### download() [Section titled “download()”](#download) Download specific languages to the local cache. Returns the number of distinct languages available after the call. Already compiled or cached languages are included in the count. Aliases are resolved before counting, so `["shell", "bash"]` names one language and returns 1. **Errors:** Returns an error if any language is not available in the manifest or if the download fails. **Signature:** ```typescript function download(names: Array): number ``` **Example:** ```typescript const result = download([]); ``` **Parameters:** | Name | Type | Required | Description | | ------- | --------------- | -------- | ----------- | | `names` | `Array` | Yes | The names | **Returns:** `number` **Errors:** Throws `Error` with a descriptive message. *** #### prefetch() [Section titled “prefetch()”](#prefetch) Prefetch grammars: download any not already loadable from disk, then load every requested language into the process registry so a subsequent hot loop only parses. Unlike `download()`, this does not trust in-memory availability — it downloads whenever a grammar is not actually loadable from disk (fixing the case where a known-but-not-downloaded grammar is reported present), then resolves and caches every requested language. Call it once, up front, before a parallel workload. **Errors:** Returns `Error.Download` if a required grammar cannot be fetched, or `Error.LanguageNotFound` if a requested name is unknown. **Signature:** ```typescript function prefetch(languages: Array): void ``` **Example:** ```typescript prefetch([]); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | --------------- | -------- | ------------- | | `languages` | `Array` | Yes | The languages | **Returns:** No return value. **Errors:** Throws `Error` with a descriptive message. *** #### downloadAll() [Section titled “downloadAll()”](#downloadall) Download all available languages from the remote manifest. Downloads the platform bundle and extracts every library it contains. Languages that appear in the manifest but are absent from the bundle (e.g. grammars that failed to compile at release time) are silently skipped — they are not treated as an error. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns an error if the manifest cannot be fetched or the bundle download fails. **Signature:** ```typescript function downloadAll(): number ``` **Example:** ```typescript const result = downloadAll(); ``` **Returns:** `number` **Errors:** Throws `Error` with a descriptive message. *** #### downloadGroup() [Section titled “downloadGroup()”](#downloadgroup) Download every language in a named group. Groups are defined by the remote manifest, not by this library, and let you ensure a curated set of related grammars in one call instead of listing each name to `download()`. Already-cached languages are skipped. Call `manifest_groups` to discover the group names the manifest actually defines. The published manifest currently defines a single group, `"all"`; earlier revisions of this documentation advertised `"web"`, `"data"`, and `"systems"`, which the manifest has never contained, so every call following that example failed. Do not hardcode a group name without checking. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns `Error.Download` if the manifest cannot be fetched, if the group is unknown — the message lists the groups the manifest defines — or if any constituent language fails to download. **Signature:** ```typescript function downloadGroup(name: string): number ``` **Example:** ```typescript const result = downloadGroup("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `number` **Errors:** Throws `Error` with a descriptive message. *** #### manifestLanguages() [Section titled “manifestLanguages()”](#manifestlanguages) Return all language names available in the remote manifest (371). Fetches (and caches) the remote manifest to discover the full list of downloadable languages. Use `downloaded_languages` to list what is already cached locally. **Errors:** Returns an error if the manifest cannot be fetched. **Signature:** ```typescript function manifestLanguages(): Array ``` **Example:** ```typescript const result = manifestLanguages(); ``` **Returns:** `Array` **Errors:** Throws `Error` with a descriptive message. *** #### manifestGroups() [Section titled “manifestGroups()”](#manifestgroups) Return the names of every language group the remote manifest defines, sorted. Group names are manifest data, not a compile-time constant of this library, so this is the only reliable way to learn what `download_group` and `PackConfig.groups` accept. The published manifest currently defines just `"all"`. **Errors:** Returns `Error.Download` if the manifest cannot be fetched. **Signature:** ```typescript function manifestGroups(): Array ``` **Example:** ```typescript const result = manifestGroups(); ``` **Returns:** `Array` **Errors:** Throws `Error` with a descriptive message. *** #### downloadedLanguages() [Section titled “downloadedLanguages()”](#downloadedlanguages) Return languages that are already downloaded and cached locally. Does not perform any network requests. Returns an empty list if the cache directory does not exist or cannot be read. **Signature:** ```typescript function downloadedLanguages(): Array ``` **Example:** ```typescript const result = downloadedLanguages(); ``` **Returns:** `Array` *** #### cleanCache() [Section titled “cleanCache()”](#cleancache) Delete all cached parser shared libraries. Resets the cache registration so the next call to `get_language` or a download function will re-register the (now empty) cache directory. **Errors:** Returns an error if the cache directory cannot be removed. **Signature:** ```typescript function cleanCache(): void ``` **Example:** ```typescript cleanCache(); ``` **Returns:** No return value. **Errors:** Throws `Error` with a descriptive message. *** #### cacheDir() [Section titled “cacheDir()”](#cachedir) Return the effective cache directory path. This is `{base}/tree-sitter-language-pack/v{version}/libs/`, where `{base}` is either the custom BASE directory set via `configure` / `init` (`PackConfig.cache_dir`) or the platform default cache directory — both are suffixed identically, so a custom `cache_dir` is never used as the final libs path. The default resolves to `~/.cache/tree-sitter-language-pack/v{version}/libs/` on a typical Unix system. **Errors:** Returns an error if no cache directory can be resolved: `version` is somehow invalid, or (with no custom `cache_dir` configured) the platform reports none and `TREE_SITTER_LANGUAGE_PACK_CACHE_DIR` is unset. This crate no longer falls back to the temporary directory for the latter case — see #101 H2. **Signature:** ```typescript function cacheDir(): string ``` **Example:** ```typescript const result = cacheDir(); ``` **Returns:** `string` **Errors:** Throws `Error` with a descriptive message. *** ### Types [Section titled “Types”](#types) #### ByteRange [Section titled “ByteRange”](#byterange) A byte range — start (inclusive) to end (exclusive). | Field | Type | Default | Description | | ------- | -------- | ------- | ---------------------------- | | `start` | `number` | — | Inclusive start byte offset. | | `end` | `number` | — | Exclusive end byte offset. | *** #### ChunkContext [Section titled “ChunkContext”](#chunkcontext) Metadata for a single chunk of source code. | Field | Type | Default | Description | | ---------------- | ---------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `string` | — | Language name used to parse this chunk. | | `chunkIndex` | `number` | — | Zero-indexed position of this chunk within the file’s chunk list. | | `totalChunks` | `number` | — | Total number of chunks the file was split into. | | `nodeTypes` | `Array` | `[]` | Tree-sitter node kinds that appear at the top level of this chunk. | | `contextPath` | `Array` | `[]` | Hierarchical path of enclosing structural items (e.g., `["MyClass", "my_method"]`). | | `symbolsDefined` | `Array` | `[]` | Names of symbols defined within this chunk. | | `comments` | `Array` | `[]` | Comments contained within this chunk. | | `docstrings` | `Array` | `[]` | Docstrings contained within this chunk. Populated only for Python — the same language for which `ProcessResult.docstrings` is populated, and by the same classifier. Always empty for every other language. | | `hasErrorNodes` | `boolean` | — | Whether this chunk contains any tree-sitter error nodes. | *** #### CodeChunk [Section titled “CodeChunk”](#codechunk) A chunk of source code with rich metadata. | Field | Type | Default | Description | | ----------- | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `content` | `string` | — | The raw source text of this chunk. | | `startByte` | `number` | — | Inclusive start byte offset of this chunk in the original source. | | `endByte` | `number` | — | Exclusive end byte offset of this chunk in the original source. | | `startLine` | `number` | — | Zero-indexed start line of this chunk. | | `endLine` | `number` | — | Zero-indexed row of the last byte actually included in this chunk (inclusive — the same row a `Span.end_line` would report for a node ending on that byte). Computed the same way regardless of whether the source has a trailing newline: it is always the row of `end_byte - 1`, never a phantom row past the file’s real content. | | `metadata` | `ChunkContext` | — | Contextual metadata about this chunk. | *** #### CommentInfo [Section titled “CommentInfo”](#commentinfo) A comment extracted from source code. | Field | Type | Default | Description | | ---------------- | ---------------- | ------------------ | ----------------------------------------------------------------- | | `text` | `string` | — | The raw text content of the comment. | | `kind` | `CommentKind` | `CommentKind.Line` | The kind of comment (line, block, or doc). | | `span` | `Span` | — | Source span covering the comment. | | `associatedNode` | `string \| null` | `null` | Name of the syntax node this comment is directly associated with. | *** #### DataAttribute [Section titled “DataAttribute”](#dataattribute) An XML-style attribute attached to an `Element` node. Populated only for `DataNodeKind.Element`; always empty for `KeyValue` and `Sequence` nodes. | Field | Type | Default | Description | | ------- | -------- | ------- | --------------------------------------------------------------- | | `name` | `string` | — | Attribute name (e.g. `"class"`, `"href"`). | | `value` | `string` | — | Attribute value as a raw string (quotes stripped). | | `span` | `Span` | — | Source span covering the entire `name="value"` attribute token. | *** #### DataNode [Section titled “DataNode”](#datanode) A node in the hierarchical data tree produced by data-format extraction. When `ProcessConfig.data_extraction` is `true`, `ProcessResult.data` is populated with a root `DataNode` whose `children` mirror the structure of the parsed file. The `kind` field determines which other fields are meaningful: | `kind` | `key` | `value` | `attributes` | `children` | | ---------- | ------------------------- | ------------ | ------------ | -------------- | | `KeyValue` | key / mapping key / index | leaf value | empty | nested map | | `Element` | XML tag name | text content | XML attrs | child elements | | `Sequence` | positional index (`"0"`) | leaf value | empty | sub-items | | Field | Type | Default | Description | | ------------ | ---------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------- | | `kind` | `DataNodeKind` | `DataNodeKind.KeyValue` | Whether this node is a key/value pair, XML element, or sequence item. | | `key` | `string \| null` | `null` | Key, attribute name, tag name, or positional index (`"0"`, `"1"`, …). `null` at the document root. | | `value` | `string \| null` | `null` | Leaf scalar value, if any. `null` for containers (objects, arrays, XML elements with child elements). | | `attributes` | `Array` | `[]` | Attributes on element-shape nodes (XML `STag` attributes). Empty for all other kinds. | | `children` | `Array` | `[]` | Children for nested containers and XML element bodies. | | `span` | `Span` | — | Source span covering this node in the original source file. | *** #### Diagnostic [Section titled “Diagnostic”](#diagnostic) A diagnostic (syntax error, missing node, etc.) from parsing. | Field | Type | Default | Description | | ---------- | -------------------- | -------------------------- | ---------------------------------------------- | | `message` | `string` | — | Human-readable description of the diagnostic. | | `severity` | `DiagnosticSeverity` | `DiagnosticSeverity.Error` | Severity of the diagnostic. | | `span` | `Span` | — | Source span where the diagnostic was detected. | *** #### DocSection [Section titled “DocSection”](#docsection) A section within a docstring (e.g., Args, Returns, Raises). | Field | Type | Default | Description | | ------------- | ---------------- | ------- | ------------------------------------------------------- | | `kind` | `string` | — | Section kind (e.g., `"args"`, `"returns"`, `"raises"`). | | `name` | `string \| null` | `null` | Parameter or return value name, if applicable. | | `description` | `string` | — | Description text for this section. | *** #### DocstringInfo [Section titled “DocstringInfo”](#docstringinfo) A docstring extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | `string` | — | The raw text of the docstring. | | `format` | `DocstringFormat` | `DocstringFormat.PythonTripleQuote` | The docstring format (Python, JSDoc, Rustdoc, etc.). | | `span` | `Span` | — | Source span covering the docstring. | | `associatedItem` | `string \| null` | `null` | Name of the item this docstring documents. | | `parsedSections` | `Array` | `[]` | Parsed sections of the docstring (Args, Returns, Raises, etc.). **Reserved: not yet populated.** Always empty, for every `DocstringFormat`. Parsing a docstring body into sections requires implementing each convention’s own layout (Google/NumPy/reST style for Python, `@param`/`@returns` for JSDoc/Javadoc, and so on), which no extractor here does yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | *** #### DownloadManager [Section titled “DownloadManager”](#downloadmanager) Manages downloading and caching of pre-built parser shared libraries. ##### Methods [Section titled “Methods”](#methods) ###### new() [Section titled “new()”](#new) Create a new download manager for the given version. **Errors:** Returns `Error.Download` if `version` is empty, contains a path separator or `..`, or contains a character outside `[A-Za-z0-9.+-]` — see `validate_version` — or if no cache directory can be resolved (see `Self.default_cache_dir`). **Signature:** ```typescript static new(version: string): DownloadManager ``` **Example:** ```typescript const result = DownloadManager.new("value"); ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ----------- | | `version` | `string` | Yes | The version | **Returns:** `DownloadManager` **Errors:** Throws `Error` with a descriptive message. ###### installedLanguages() [Section titled “installedLanguages()”](#installedlanguages) List languages that are already downloaded and cached. Derived from the on-disk cache filenames, one canonical name per file, plus every alias that resolves to it (via `aliases_for`) — so this list agrees with the user-facing `LanguageRegistry.available_languages` about which names are “available”; both report `"shell"` once `bash` is cached, for example. A previous version reported canonical names only, which could never agree with `available_languages()`. See #107. Returns an empty list if the cache directory does not exist. If it exists but cannot be read (e.g. a permission error), also returns an empty list — changing this to a `Result` would be a breaking change across every language binding — but logs a `tracing.warn!` so the failure is not silently indistinguishable from “nothing installed”. **Signature:** ```typescript installedLanguages(): Array ``` **Example:** ```typescript const result = instance.installedLanguages(); ``` **Returns:** `Array` ###### downloadAllBestEffort() [Section titled “downloadAllBestEffort()”](#downloadallbesteffort) Download the platform bundle and extract every library file it contains. Unlike `Self.ensure_languages`, this does not check the manifest language list against archive contents — it simply extracts all `.so`/`.dylib`/`.dll` files from the bundle. Languages in the manifest that are missing from the archive are silently ignored rather than returning an error. Returns the number of library files extracted (including those already cached). **Signature:** ```typescript downloadAllBestEffort(): number ``` **Example:** ```typescript const result = instance.downloadAllBestEffort(); ``` **Returns:** `number` **Errors:** Throws `Error` with a descriptive message. ###### cleanCache() [Section titled “cleanCache()”](#cleancache-1) Remove all cached parser libraries. Acquires the cross-process lock so `clean_cache` cannot race a concurrent downloader (avoids Windows sharing-violation errors against an in-flight bundle write). The `.download.lock` file itself is **not** removed — it is permanent infrastructure; deleting it could allow a concurrent process that already opened the file to continue holding a stale lock handle while a new process opens a fresh inode, breaking the mutual-exclusion guarantee. **Signature:** ```typescript cleanCache(): void ``` **Example:** ```typescript instance.cleanCache(); ``` **Returns:** No return value. **Errors:** Throws `Error` with a descriptive message. *** #### ExportInfo [Section titled “ExportInfo”](#exportinfo) An export statement extracted from source code. | Field | Type | Default | Description | | ------ | ------------ | ------------------ | -------------------------------------------------- | | `name` | `string` | — | The exported name. | | `kind` | `ExportKind` | `ExportKind.Named` | The kind of export (named, default, or re-export). | | `span` | `Span` | — | Source span covering the export statement. | *** #### FileMetrics [Section titled “FileMetrics”](#filemetrics) Aggregate metrics for a source file. | Field | Type | Default | Description | | -------------- | -------- | ------- | -------------------------------------------------------------- | | `totalLines` | `number` | — | Total number of lines (including blank and comment lines). | | `codeLines` | `number` | — | Number of lines containing non-blank, non-comment source code. | | `commentLines` | `number` | — | Number of lines that are entirely comments. | | `blankLines` | `number` | — | Number of blank (whitespace-only) lines. | | `totalBytes` | `number` | — | Total byte length of the source file. | | `nodeCount` | `number` | — | Total number of nodes in the syntax tree. | | `errorCount` | `number` | — | Number of error nodes in the syntax tree (parse errors). | | `maxDepth` | `number` | — | Maximum nesting depth reached in the syntax tree. | *** #### ImportInfo [Section titled “ImportInfo”](#importinfo) An import statement extracted from source code. | Field | Type | Default | Description | | ------------ | ---------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `source` | `string` | — | The module or path being imported from. | | `items` | `Array` | `[]` | Specific names imported from the source module. For `import a, b` / `from m import a, b`, every entry’s base name (never the alias). For a JavaScript/TypeScript named-imports clause (`import { a, b as c } from 'm'`), every specifier’s original name. Populated for Python and JavaScript/TypeScript only. Always empty for every other language this library recognises import statements for — Rust, Go, Java, Kotlin, and Elixir (`import`/`alias`/`require`/`use`) — and for a JS/TS namespace import (`import * as ns`) or default import (`import x from 'm'`), neither of which names individual items. | | `alias` | `string \| null` | `null` | Alias assigned to the import (e.g., `import numpy as np`). Populated for Python’s single-name form (`import numpy as np`, `from m import a as b`) and JavaScript/TypeScript’s namespace form (`import * as ns from 'm'`) or a named-imports clause naming exactly one specifier (`import { a as b } from 'm'`). `null` for Rust, Go, Java, Kotlin, and Elixir (which has its own `as:` alias option on `alias` directives, not yet extracted here) — and for a Python statement that aliases several names at once (`import os, sys as s`), where there is no single alias to report for the statement as a whole, so only `items` is populated for it. | | `isWildcard` | `boolean` | — | Whether this is a wildcard import (e.g., `import *` or `use foo.*`). Detected from the syntax tree — a dedicated wildcard node (`wildcard_import` in Python, `use_wildcard` in Rust) or a bare `*` token outside of string-literal content — not by searching the import’s source text for a `*` character, so a glob in an import path string (`import a from './glob*.js'`) is not mistaken for one. | | `span` | `Span` | — | Source span covering the import statement. | *** #### Language [Section titled “Language”](#language) *** #### LanguageRegistry [Section titled “LanguageRegistry”](#languageregistry) Thread-safe registry of tree-sitter language parsers. Manages both statically compiled and dynamically loaded language grammars. Use `LanguageRegistry.new()` for the default registry, or access the global instance via the module-level convenience functions (`get_language`, `available_languages`, etc.). ##### Methods [Section titled “Methods”](#methods-1) ###### new() [Section titled “new()”](#new-1) Create a new registry populated with all statically compiled languages. When the `dynamic-loading` feature is enabled, the registry also knows about dynamically loadable grammars and will load them on demand. **Signature:** ```typescript static new(): LanguageRegistry ``` **Example:** ```typescript const result = LanguageRegistry.new(); ``` **Returns:** `LanguageRegistry` ###### getLanguage() [Section titled “getLanguage()”](#getlanguage-1) Get a tree-sitter `Language` by name. Resolves aliases (e.g., `"shell"` -> `"bash"`, `"makefile"` -> `"make"`), then looks up the language in the static table. When the `dynamic-loading` feature is enabled, falls back to loading a shared library on demand. **Errors:** Returns `Error.LanguageNotFound` if the name (after alias resolution) does not match any known grammar. **Signature:** ```typescript getLanguage(name: string): Language ``` **Example:** ```typescript const result = instance.getLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `Language` **Errors:** Throws `Error` with a descriptive message. ###### availableLanguages() [Section titled “availableLanguages()”](#availablelanguages-1) List all available language names, sorted and deduplicated. Includes statically compiled languages, dynamically loadable languages (if the `dynamic-loading` feature is enabled), and all configured aliases. **Signature:** ```typescript availableLanguages(): Array ``` **Example:** ```typescript const result = instance.availableLanguages(); ``` **Returns:** `Array` ###### hasParser() [Section titled “hasParser()”](#hasparser) Check whether this language can be parsed right now, without downloading. Resolves aliases, then answers from exactly the lookup `get_language` performs: the statically compiled table, the already-loaded dynamic grammars, and the parser shared libraries present in the primary and extra (download-cache) library directories. It never performs network I/O. A previous implementation consulted only the statically compiled table. That table is empty in every build that does not set `TSLP_LANGUAGES`, so the function answered `false` for languages this registry parses perfectly well. Contrast `has_language`, which is also `true` for a grammar that is merely *known to the manifest* and would have to be downloaded first. The pair distinguishes “we can parse it offline, now” from “we recognise the name”. The first `true` answer for a dynamic grammar loads its shared library: loading is the only way to know the grammar is usable, since a truncated or wrong-architecture library exists on disk but cannot parse. Loads are cached process-wide, so repeat calls are cheap. **Signature:** ```typescript hasParser(name: string): boolean ``` **Example:** ```typescript const result = instance.hasParser("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `boolean` ###### hasLanguage() [Section titled “hasLanguage()”](#haslanguage-1) Check whether a language is available by name or alias. Returns `true` if the language can be loaded, either from the static table or from a dynamic library on disk. Every branch is one more way to answer `true`, so they are ordered cheapest-first and the filesystem is only consulted once every in-memory source has said no. Probing the loaded-grammar map and the manifest ahead of the `stat` calls is what keeps this off the syscall path for the languages a process actually uses. **Signature:** ```typescript hasLanguage(name: string): boolean ``` **Example:** ```typescript const result = instance.hasLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `boolean` ###### languageCount() [Section titled “languageCount()”](#languagecount-1) Return the total number of available languages (including aliases). Counts the same set `available_languages` lists, without materialising or sorting it. **Signature:** ```typescript languageCount(): number ``` **Example:** ```typescript const result = instance.languageCount(); ``` **Returns:** `number` ###### process() [Section titled “process()”](#process-1) Parse source code and extract file intelligence based on config in a single pass. **Errors:** Returns `Error.InvalidRange` if the config is invalid (see `ProcessConfig.validate`) or if the source exceeds the configured `max_source_bytes`; `Error.LanguageNotFound` if the language is unknown; or `Error.ParseFailed` if parsing produces no tree. **Signature:** ```typescript process(source: string, config: ProcessConfig): ProcessResult ``` **Example:** ```typescript const result = instance.process("value", new ProcessConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `string` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Throws `Error` with a descriptive message. *** #### Node [Section titled “Node”](#node) A single syntax node within a `Tree`. Nodes hold a strong reference to their parent tree so they remain valid regardless of how the tree is moved or stored at the FFI boundary. ##### Methods [Section titled “Methods”](#methods-2) ###### kind() [Section titled “kind()”](#kind) Return the node’s kind name (e.g. `"function_definition"`). **Signature:** ```typescript kind(): string ``` **Example:** ```typescript const result = instance.kind(); ``` **Returns:** `string` ###### kindId() [Section titled “kindId()”](#kindid) Return the node’s numeric kind ID. Tree-sitter assigns a stable `u16` ID to every node kind in a grammar (e.g. `"function_definition" → 42`). Comparing `kind_id()` is cheaper than comparing the string `kind()` in tight AST loops. **Signature:** ```typescript kindId(): number ``` **Example:** ```typescript const result = instance.kindId(); ``` **Returns:** `number` ###### startByte() [Section titled “startByte()”](#startbyte) Return the inclusive start byte offset of this node. **Signature:** ```typescript startByte(): number ``` **Example:** ```typescript const result = instance.startByte(); ``` **Returns:** `number` ###### endByte() [Section titled “endByte()”](#endbyte) Return the exclusive end byte offset of this node. **Signature:** ```typescript endByte(): number ``` **Example:** ```typescript const result = instance.endByte(); ``` **Returns:** `number` ###### byteRange() [Section titled “byteRange()”](#byterange-1) Return the node’s byte range as a `ByteRange`. Callers should slice their own source bytes — this is a zero-copy text accessor. **Signature:** ```typescript byteRange(): ByteRange ``` **Example:** ```typescript const result = instance.byteRange(); ``` **Returns:** `ByteRange` ###### startPosition() [Section titled “startPosition()”](#startposition) Return the start `Point` (row, column). **Signature:** ```typescript startPosition(): Point ``` **Example:** ```typescript const result = instance.startPosition(); ``` **Returns:** `Point` ###### endPosition() [Section titled “endPosition()”](#endposition) Return the end `Point` (row, column). **Signature:** ```typescript endPosition(): Point ``` **Example:** ```typescript const result = instance.endPosition(); ``` **Returns:** `Point` ###### isNamed() [Section titled “isNamed()”](#isnamed) True when this node is named (not punctuation/whitespace). **Signature:** ```typescript isNamed(): boolean ``` **Example:** ```typescript const result = instance.isNamed(); ``` **Returns:** `boolean` ###### isError() [Section titled “isError()”](#iserror) True when this is an error node. **Signature:** ```typescript isError(): boolean ``` **Example:** ```typescript const result = instance.isError(); ``` **Returns:** `boolean` ###### isMissing() [Section titled “isMissing()”](#ismissing) True when this is a missing-token node. **Signature:** ```typescript isMissing(): boolean ``` **Example:** ```typescript const result = instance.isMissing(); ``` **Returns:** `boolean` ###### isExtra() [Section titled “isExtra()”](#isextra) True when this is an “extra” node (e.g. a comment). **Signature:** ```typescript isExtra(): boolean ``` **Example:** ```typescript const result = instance.isExtra(); ``` **Returns:** `boolean` ###### hasError() [Section titled “hasError()”](#haserror) True when this node or any descendant is an error. **Signature:** ```typescript hasError(): boolean ``` **Example:** ```typescript const result = instance.hasError(); ``` **Returns:** `boolean` ###### parent() [Section titled “parent()”](#parent) Return this node’s parent, if any. **Signature:** ```typescript parent(): Node | null ``` **Example:** ```typescript const result = instance.parent(); ``` **Returns:** `Node | null` ###### child() [Section titled “child()”](#child) Return the i-th child of this node, if any. **Signature:** ```typescript child(index: number): Node | null ``` **Example:** ```typescript const result = instance.child(42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | -------- | -------- | ----------- | | `index` | `number` | Yes | The index | **Returns:** `Node | null` ###### childCount() [Section titled “childCount()”](#childcount) Total number of children (including unnamed). **Signature:** ```typescript childCount(): number ``` **Example:** ```typescript const result = instance.childCount(); ``` **Returns:** `number` ###### namedChild() [Section titled “namedChild()”](#namedchild) Return the i-th named child of this node, if any. **Signature:** ```typescript namedChild(index: number): Node | null ``` **Example:** ```typescript const result = instance.namedChild(42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | -------- | -------- | ----------- | | `index` | `number` | Yes | The index | **Returns:** `Node | null` ###### namedChildCount() [Section titled “namedChildCount()”](#namedchildcount) Number of named children of this node. **Signature:** ```typescript namedChildCount(): number ``` **Example:** ```typescript const result = instance.namedChildCount(); ``` **Returns:** `number` ###### childByFieldName() [Section titled “childByFieldName()”](#childbyfieldname) Look up a child by its grammar-defined field name. **Signature:** ```typescript childByFieldName(name: string): Node | null ``` **Example:** ```typescript const result = instance.childByFieldName("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `Node | null` ###### toSexp() [Section titled “toSexp()”](#tosexp) Return the S-expression form of this node’s subtree. **Signature:** ```typescript toSexp(): string ``` **Example:** ```typescript const result = instance.toSexp(); ``` **Returns:** `string` ###### walk() [Section titled “walk()”](#walk) Return a `TreeCursor` positioned at this node. **Signature:** ```typescript walk(): TreeCursor ``` **Example:** ```typescript const result = instance.walk(); ``` **Returns:** `TreeCursor` *** #### PackConfig [Section titled “PackConfig”](#packconfig) Configuration for the tree-sitter language pack. Controls cache directory and which languages to pre-download. Can be loaded from a TOML file, constructed programmatically, or passed as a dict/object from language bindings. | Field | Type | Default | Description | | ----------- | ----------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cacheDir` | `string \| null` | `null` | Override the BASE directory the parser cache lives under. This is a base, not the final library path: the crate appends `tree-sitter-language-pack/v{version}/libs` to it, exactly as it does to the platform default. So `cache_dir = "/tmp/my-parsers"` resolves to `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`. The suffix is not cosmetic. It keeps the whole cache tree — manifest, bundles and lock file included — inside a directory this library owns and versions. Earlier releases used this path verbatim, which put those files in the configured directory’s PARENT and let a cache built by one crate version be reused by another. Default base: the platform cache dir, e.g. `~/.cache` on Linux. | | `languages` | `Array \| null` | `[]` | Languages to pre-download on init. Each entry is a language name (e.g. `"python"`, `"rust"`). | | `groups` | `Array \| null` | `[]` | Language groups to pre-download. Group names come from the remote manifest, so the valid set is not fixed by this library; the published manifest currently defines only `"all"`. Call `manifest_groups` to enumerate them. An unknown name makes `init` fail. | *** #### Parser [Section titled “Parser”](#parser) A tree-sitter parser configured for one language at a time. ##### Methods [Section titled “Methods”](#methods-3) ###### new() [Section titled “new()”](#new-2) Construct a new parser with no language set and no parse limits. Call `Parser.set_language` before parsing. Limits are opt-in via `set_max_source_bytes` and `set_parse_timeout_ms`; both default to unbounded so that existing callers are unaffected. **Signature:** ```typescript static new(): Parser ``` **Example:** ```typescript const result = Parser.new(); ``` **Returns:** `Parser` ###### setMaxSourceBytes() [Section titled “setMaxSourceBytes()”](#setmaxsourcebytes) Refuse to parse sources longer than `max_bytes`. `null` (the default) means no limit. Over-limit input makes `parse` and `parse_bytes` return `null` after emitting a `WARN`; input is never silently truncated. See `RECOMMENDED_MAX_SOURCE_BYTES`. **Signature:** ```typescript setMaxSourceBytes(maxBytes: number): void ``` **Example:** ```typescript instance.setMaxSourceBytes(42); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ---------------- | -------- | ------------- | | `maxBytes` | `number \| null` | No | The max bytes | **Returns:** No return value. ###### setParseTimeoutMs() [Section titled “setParseTimeoutMs()”](#setparsetimeoutms) Cancel a parse that exceeds `timeout_ms` milliseconds of wall clock. `null` (the default) means no budget. Cancellation runs through tree-sitter’s parse progress callback, so it is granular to that callback’s interval rather than exact. See `RECOMMENDED_PARSE_TIMEOUT_MS`. **Signature:** ```typescript setParseTimeoutMs(timeoutMs: number): void ``` **Example:** ```typescript instance.setParseTimeoutMs(42); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | ---------------- | -------- | -------------- | | `timeoutMs` | `number \| null` | No | The timeout ms | **Returns:** No return value. ###### setLanguage() [Section titled “setLanguage()”](#setlanguage) Configure the parser to use the language identified by name (e.g. `"python"`). Resolves the language through the global registry — auto-downloading if necessary, when the `download` feature is enabled. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language ABI is incompatible. **Signature:** ```typescript setLanguage(name: string): void ``` **Example:** ```typescript instance.setLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** No return value. **Errors:** Throws `Error` with a descriptive message. ###### parse() [Section titled “parse()”](#parse) Parse a UTF-8 source string. Returns `null` if no language is set, if the parse was cancelled by the configured timeout, or if the source exceeds the configured size limit. Each non-parse outcome is logged, so an empty result is never silent. ###### Concurrency [Section titled “Concurrency”](#concurrency) Parsing runs fully in parallel across threads for almost every language — no lock is taken. The exception is the small set of grammars whose external scanner keeps mutable process-global state (currently just `properties`): parses of that language are serialized against each other through an internal per-language lock, so that concurrent threads can’t corrupt shared scanner state. Every other language is unaffected by that lock and never waits on it. **Signature:** ```typescript parse(source: string): Tree | null ``` **Example:** ```typescript const result = instance.parse("value"); ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------- | -------- | ----------- | | `source` | `string` | Yes | The source | **Returns:** `Tree | null` ###### parseBytes() [Section titled “parseBytes()”](#parsebytes) Parse a raw byte slice. Same outcomes as `parse`, including the concurrency behaviour documented there. **Signature:** ```typescript parseBytes(source: Buffer): Tree | null ``` **Example:** ```typescript const result = instance.parseBytes(Buffer.from("data")); ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------- | -------- | ----------- | | `source` | `Buffer` | Yes | The source | **Returns:** `Tree | null` ###### reset() [Section titled “reset()”](#reset) Reset internal state. The next call to `parse` will not be incremental. **Signature:** ```typescript reset(): void ``` **Example:** ```typescript instance.reset(); ``` **Returns:** No return value. *** #### Point [Section titled “Point”](#point) A source position — row + column, zero-indexed. | Field | Type | Default | Description | | -------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `row` | `number` | — | Zero-indexed row number. | | `column` | `number` | — | Zero-indexed column, counted in **bytes** from the start of the row. This is `tree_sitter.Point.column` verbatim, and tree-sitter defines it as a byte offset — not characters, and not UTF-16 code units. Measured on a row of the form `x = ''` where `` is a single 4-byte character (an emoji), the string node reports columns `4..10`, identical to its byte range; the character columns would be `4..7` and the UTF-16 columns `4..8`. Anything that builds LSP positions (UTF-16) or editor caret columns (characters) from this field is silently wrong on every row containing a non-ASCII byte, and must re-measure the row against the source text instead. Earlier releases documented this field as UTF-16 code units; that was never what the value contained. | *** #### ProcessConfig [Section titled “ProcessConfig”](#processconfig) Configuration for the `process()` function. Controls which analysis features are enabled and whether chunking is performed. | Field | Type | Default | Description | | ---------------- | ---------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `string` | `""` | Language name (required). | | `structure` | `boolean` | `true` | Extract structural items (functions, classes, etc.). Default: true. | | `imports` | `boolean` | `true` | Extract import statements. Default: true. | | `exports` | `boolean` | `true` | Extract export statements. Default: true. | | `comments` | `boolean` | `false` | Extract comments. Default: false. | | `docstrings` | `boolean` | `false` | Extract docstrings. Default: false. | | `symbols` | `boolean` | `false` | Extract symbol definitions. Default: false. | | `diagnostics` | `boolean` | `false` | Include parse diagnostics. Default: false. | | `chunkMaxSize` | `number \| null` | `null` | Maximum chunk size in bytes. `null` disables chunking. `Some(0)` is rejected by `ProcessConfig.validate` with `Error.InvalidRange`. A zero-sized chunk limit previously produced an empty chunk list and silently discarded the whole source; use `null` to mean “do not chunk”. | | `dataExtraction` | `boolean` | `false` | Extract hierarchical key/value data tree from data-format files. Default: false. When `true`, `ProcessResult.data` is populated with a `DataNode` tree for supported languages: JSON, YAML, TOML, `.properties`, HCL/HOCON, INI, editorconfig, KDL, CUE, CSV, PSV, PO, nginx config, Caddy config, XML, and DTD. For languages outside this set the field is left as `null`. | | `maxSourceBytes` | `number \| null` | `null` | Reject source longer than this many bytes instead of parsing it. Default: `null` (unbounded). Tree-sitter allocates and walks proportionally to input size, so an unbounded parse of attacker-supplied input is a denial-of-service vector. The default stays unbounded for backward compatibility; services handling untrusted input should opt in, e.g. with `RECOMMENDED_MAX_SOURCE_BYTES`. Exceeding the limit fails the call with `Error.InvalidRange` — the source is never silently truncated. | | `parseTimeoutMs` | `number \| null` | `null` | Wall-clock budget for the parse step, in milliseconds. Default: `null` (no timeout). Enforced through tree-sitter’s parse progress callback, which the parser invokes periodically; cancellation is therefore granular to that callback interval rather than exact. A parse that exceeds the budget fails with `Error.ParseTimeout`. | *** #### ProcessResult [Section titled “ProcessResult”](#processresult) Complete analysis result from processing a source file. Contains metrics, structural analysis, imports/exports, comments, docstrings, symbols, diagnostics, and optionally chunked code segments. Fields are populated based on the `ProcessConfig` flags. | Field | Type | Default | Description | | ------------- | ---------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `string` | — | The language name used to parse the source file. | | `metrics` | `FileMetrics` | — | File-level metrics (line counts, byte size, error count). | | `structure` | `Array` | `[]` | Top-level structural items (functions, classes, etc.). | | `imports` | `Array` | `[]` | Import statements extracted from the source. | | `exports` | `Array` | `[]` | Export statements extracted from the source. | | `comments` | `Array` | `[]` | Comments extracted from the source. | | `docstrings` | `Array` | `[]` | Docstrings extracted from the source. | | `symbols` | `Array` | `[]` | Symbol definitions (variables, types, functions) extracted from the source. | | `diagnostics` | `Array` | `[]` | Parse diagnostics (syntax errors, missing nodes) from tree-sitter. | | `chunks` | `Array` | `[]` | Syntax-aware code chunks produced when chunking is enabled. | | `data` | `DataNode \| null` | `null` | Hierarchical data tree extracted when `config.data_extraction` is `true`. Populated for supported data-format languages (JSON, YAML, TOML, properties, HCL, INI, XML, CSV, and more). `null` when `data_extraction` is `false` (the default) or when the language is not a recognised data format. See `DataNode` for the shape of the returned tree. | *** #### Span [Section titled “Span”](#span) Byte and line/column range in source code. Represents both byte offsets (for slicing) and human-readable line/column positions (for display and diagnostics). | Field | Type | Default | Description | | ------------- | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `startByte` | `number` | — | Inclusive start byte offset in the source. | | `endByte` | `number` | — | Exclusive end byte offset in the source. | | `startLine` | `number` | — | Zero-indexed line number of the span’s start. | | `startColumn` | `number` | — | Zero-indexed column of the span’s start, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | | `endLine` | `number` | — | Zero-indexed line number of the span’s end. | | `endColumn` | `number` | — | Zero-indexed column of the span’s end, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | *** #### StructureItem [Section titled “StructureItem”](#structureitem) A structural item (function, class, struct, etc.) in source code. | Field | Type | Default | Description | | ------------ | ---------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `kind` | `StructureKind` | `StructureKind.Function` | The kind of structural item. | | `name` | `string \| null` | `null` | The declared name of the item, if present. | | `visibility` | `string \| null` | `null` | Visibility modifier (e.g., `"pub"`, `"public"`, `"private"`). | | `span` | `Span` | — | Source span covering the entire item declaration. | | `children` | `Array` | `[]` | Nested structural items (e.g., methods within a class). | | `decorators` | `Array` | `[]` | Decorator or attribute names applied to the item. **Reserved: not yet populated.** Always empty, for every language. Recognising a decorator requires per-language grammar knowledge (a Python `decorated_definition` wrapper, Java/C# annotations, Rust attributes each have a different shape), which no extractor here implements yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | | `docComment` | `string \| null` | `null` | Documentation comment attached to the item, if any. The text of the comment (or run of comments) immediately preceding the item, with no blank line in between, when that comment is classified as a doc comment. Multiple adjacent single-line doc comments (Rust `///`) are joined with `\n` in source order. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`). `null` for every other language, and for a preceding comment that is not in doc-comment form (a plain `#` comment in Python, Ruby, or Elixir) — Python’s docstring convention is captured separately, as `DocstringInfo`, not through this field. | | `signature` | `string \| null` | `null` | Full signature text of the item (e.g., function parameters and return type). The item’s own source text from its start up to the start of its body (see `StructureItem.body_span`), trimmed of trailing whitespace — for example `fn add(a: i32, b: i32) -> i32` for a Rust function whose body is `{ a + b }`. `null` only when that text is empty, which does not happen for any item `StructureKind` currently reports. Populated for every language and kind this library extracts structure for, since it is derived from `body_span`’s boundary rather than per-language syntax. | | `bodySpan` | `Span \| null` | `null` | Source span covering only the body of the item, if distinct from the declaration. | *** #### SymbolInfo [Section titled “SymbolInfo”](#symbolinfo) A symbol (variable, function, type, etc.) extracted from source code. | Field | Type | Default | Description | | ---------------- | ---------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `string` | — | The name of the symbol. | | `kind` | `SymbolKind` | `SymbolKind.Variable` | The kind of symbol (variable, function, class, etc.). | | `span` | `Span` | — | Source span covering the symbol definition. | | `typeAnnotation` | `string \| null` | `null` | Explicit type annotation, if present in the source. | | `doc` | `string \| null` | `null` | Documentation comment immediately preceding this symbol, resolved by the same walk `StructureItem.doc_comment` uses (see `doc_comment_at`) — never hard-coded `null`. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`) — the languages whose comment classification recognizes a doc-kind comment. `null` for every other language (e.g. Python, Go, Ruby, which have no doc-kind comment classification), and also `null` when a symbol in a supported language simply has no doc comment immediately above it. | *** #### Tree [Section titled “Tree”](#tree) A parsed syntax tree. Cheap to clone (refcount bump). ##### Methods [Section titled “Methods”](#methods-4) ###### rootNode() [Section titled “rootNode()”](#rootnode) Return the root `Node` of this tree. **Signature:** ```typescript rootNode(): Node ``` **Example:** ```typescript const result = instance.rootNode(); ``` **Returns:** `Node` ###### walk() [Section titled “walk()”](#walk-1) Return a `TreeCursor` positioned at the root. **Signature:** ```typescript walk(): TreeCursor ``` **Example:** ```typescript const result = instance.walk(); ``` **Returns:** `TreeCursor` *** #### TreeCursor [Section titled “TreeCursor”](#treecursor) A cursor for traversing a `Tree`. ##### Methods [Section titled “Methods”](#methods-5) ###### node() [Section titled “node()”](#node-1) Return the `Node` at the cursor’s current position. **Signature:** ```typescript node(): Node ``` **Example:** ```typescript const result = instance.node(); ``` **Returns:** `Node` ###### gotoFirstChild() [Section titled “gotoFirstChild()”](#gotofirstchild) Move the cursor to the first child of the current node. Returns `true` if a child existed. **Signature:** ```typescript gotoFirstChild(): boolean ``` **Example:** ```typescript const result = instance.gotoFirstChild(); ``` **Returns:** `boolean` ###### gotoParent() [Section titled “gotoParent()”](#gotoparent) Move the cursor to the parent of the current node. Returns `true` if a parent existed. **Signature:** ```typescript gotoParent(): boolean ``` **Example:** ```typescript const result = instance.gotoParent(); ``` **Returns:** `boolean` ###### gotoNextSibling() [Section titled “gotoNextSibling()”](#gotonextsibling) Move the cursor to the next sibling of the current node. Returns `true` if a sibling existed. **Signature:** ```typescript gotoNextSibling(): boolean ``` **Example:** ```typescript const result = instance.gotoNextSibling(); ``` **Returns:** `boolean` ###### fieldName() [Section titled “fieldName()”](#fieldname) Return the field name for the current node, if any. **Signature:** ```typescript fieldName(): string | null ``` **Example:** ```typescript const result = instance.fieldName(); ``` **Returns:** `string | null` *** ### Enums [Section titled “Enums”](#enums) #### DataNodeKind [Section titled “DataNodeKind”](#datanodekind) The kind of a data node extracted from a data-format file. Classifies each node in the hierarchical `DataNode` tree returned when `data_extraction` is enabled on `ProcessConfig`. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract) Unit variants serialize as a bare string (`"KeyValue"`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ---------- | -------------------------------------------------------------------------------------------------------------------- | | `KeyValue` | A key/value pair or mapping (json/toml/properties/yaml/hcl/cue/kdl pair, or a wrapper “object”/“mapping” container). | | `Element` | An XML element with a tag name in `key` and attributes in `attributes`. | | `Sequence` | A positional sequence item (JSON array element, YAML block sequence item, CSV/PSV row or cell). | *** #### StructureKind [Section titled “StructureKind”](#structurekind) The kind of structural item found in source code. Categorizes top-level and nested declarations such as functions, classes, structs, enums, traits, and more. Use `Other` for language-specific constructs that do not fit a standard category. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-1) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | ---------------------------------------------------------------------------------------------- | | `Function` | A free-standing or associated function. | | `Method` | A method defined inside a class, struct, trait, or impl block. | | `Class` | A class definition. | | `Struct` | A struct definition. | | `Interface` | An interface or protocol definition. | | `Enum` | An enum definition. | | `Module` | A module or package declaration. | | `Trait` | A trait definition. | | `Impl` | An impl block (Rust) or similar implementation block. | | `Namespace` | A namespace declaration. | | `Other` | A language-specific construct that does not fit any standard category. — Fields: `0`: `string` | *** #### CommentKind [Section titled “CommentKind”](#commentkind) The kind of a comment found in source code. Distinguishes between single-line comments, block (multi-line) comments, and documentation comments. | Value | Description | | ------- | --------------------------------------------------------------------- | | `Line` | A single-line comment (e.g., `// ...` or `# ...`). | | `Block` | A block or multi-line comment using slash-star delimiters. | | `Doc` | A documentation comment such as `/// ...` or slash-double-star block. | *** #### DocstringFormat [Section titled “DocstringFormat”](#docstringformat) The format of a docstring extracted from source code. Identifies the docstring convention used, which varies by language (e.g., Python triple-quoted strings, JSDoc, Rustdoc `///` comments). ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-2) Unit variants serialize as a bare string (`"JSDoc"`); the `Other` variant serializes as a single-keyed object (`{"Other": "rst"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ------------------- | -------------------------------------------------------------------------------------------------- | | `PythonTripleQuote` | Python triple-quoted string docstring (`"""..."""`). | | `JsDoc` | JavaScript/TypeScript JSDoc block comment (opens with two stars, closes with star-slash). | | `Rustdoc` | Rust `///` or `//!` doc comment. | | `GoDoc` | Go doc comment (a comment block immediately preceding a declaration). | | `JavaDoc` | Java Javadoc block comment (opens with two stars, closes with star-slash). | | `Other` | A language-specific docstring format not covered by the standard variants. — Fields: `0`: `string` | *** #### ExportKind [Section titled “ExportKind”](#exportkind) The kind of an export statement found in source code. Covers named exports, default exports, and re-exports from other modules. | Value | Description | | ---------- | -------------------------------------------------------------------- | | `Named` | A named export (e.g., `export { foo }`). | | `Default` | A default export (e.g., `export default foo`). | | `ReExport` | A re-export from another module (e.g., `export { foo } from 'bar'`). | *** #### SymbolKind [Section titled “SymbolKind”](#symbolkind) The kind of a symbol definition found in source code. Categorizes symbol definitions such as variables, constants, functions, classes, types, interfaces, enums, and modules. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-3) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | --------------------------------------------------------------------------- | | `Variable` | A variable binding. | | `Constant` | A constant (immutable binding). | | `Function` | A function definition. | | `Class` | A class definition. | | `Type` | A type alias or typedef. | | `Interface` | An interface definition. | | `Enum` | An enum definition. | | `Module` | A module declaration. | | `Other` | A symbol kind not covered by the standard variants. — Fields: `0`: `string` | *** #### DiagnosticSeverity [Section titled “DiagnosticSeverity”](#diagnosticseverity) Severity level of a diagnostic produced during parsing. Used to classify parse errors, warnings, and informational messages found in the syntax tree. | Value | Description | | --------- | --------------------------------------------------------------- | | `Error` | A parse error (e.g., an `ERROR` or `MISSING` node in the tree). | | `Warning` | A warning-level diagnostic. | | `Info` | An informational diagnostic. | *** ### Errors [Section titled “Errors”](#errors) #### Error [Section titled “Error”](#error) Errors that can occur when using the tree-sitter language pack. Covers language lookup failures, parse errors, query errors, and I/O issues. Feature-gated variants are included when `config`, `download`, or related features are enabled. ##### Matching on `Error` [Section titled “Matching on Error”](#matching-on-error) The set of variants is not stable: new failure modes are added in minor releases, and `Io`, `Json`, and `Toml` exist only under certain feature combinations, so the variant set a downstream crate sees depends on which features it enables. Downstream `match`es must therefore carry a `_` arm; `#[non_exhaustive]` makes the compiler enforce that instead of letting a feature change silently break a build. ##### C ABI error codes [Section titled “C ABI error codes”](#c-abi-error-codes) Each variant alef can see carries an explicit `alef(error_code = N)` allocation that becomes a member of the generated `AlefFfiErrorCode` C enum. These numbers are a public ABI contract: **an allocated number is never reused after its variant is removed**, and a variant’s number never changes, because C callers compare against the value, not the name. New variants take the next free number. 0-4 are reserved by alef, so allocation starts at 100. An unannotated variant is emitted as the unknown code rather than as itself, which silently flattens the taxonomy — annotate every new variant. Errors are thrown as plain `Error` objects with descriptive messages. | Variant | Description | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `LanguageNotFound` | The requested language name (or alias) was not found in the registry. | | `DynamicLoad` | A dynamic shared library could not be loaded at runtime. | | `NullLanguagePointer` | The tree-sitter language function returned a null pointer for the given language name. | | `ParserSetup` | The language could not be applied to the parser (e.g., ABI version mismatch). | | `LockPoisoned` | An internal `RwLock` or `Mutex` was poisoned by a previous panic. | | `Config` | A configuration file or value was invalid or could not be applied. | | `ParseFailed` | The tree-sitter parser returned no tree for the given source input. | | `ParseTimeout` | The parse was cancelled because it exceeded its configured wall-clock budget. Raised only when a budget is configured — see `ProcessConfig.parse_timeout_ms`, which defaults to `null`. | | `QueryError` | A tree-sitter query could not be compiled or executed. | | `InvalidRange` | A byte range was invalid (e.g., end before start, or out of bounds). | | `Download` | A parser download from GitHub releases failed. | | `ChecksumMismatch` | The downloaded file’s SHA-256 digest did not match the manifest’s expected value. | | `CacheLock` | The cross-process download cache lock file could not be acquired or created. | *** # WebAssembly API Reference ## WebAssembly API Reference v1.16.1 [Section titled “WebAssembly API Reference v1.16.1”](#webassembly-api-reference-v1161) ### Functions [Section titled “Functions”](#functions) #### detectLanguageFromExtension() [Section titled “detectLanguageFromExtension()”](#detectlanguagefromextension) Detect language name from a file extension (without leading dot). Returns `null` for unrecognized extensions. The match is case-insensitive. **Signature:** ```typescript function detectLanguageFromExtension(ext: string): string | null ``` **Example:** ```typescript const result = detectLanguageFromExtension("value"); ``` **Parameters:** | Name | Type | Required | Description | | ----- | -------- | -------- | ----------- | | `ext` | `string` | Yes | The ext | **Returns:** `string | null` *** #### detectLanguageFromPath() [Section titled “detectLanguageFromPath()”](#detectlanguagefrompath) Detect language name from a file path. Extracts the file extension and looks it up. Returns `null` if the path has no extension or the extension is not recognized. **Signature:** ```typescript function detectLanguageFromPath(path: string): string | null ``` **Example:** ```typescript const result = detectLanguageFromPath("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `path` | `string` | Yes | Path to the file | **Returns:** `string | null` *** #### detectLanguageFromContent() [Section titled “detectLanguageFromContent()”](#detectlanguagefromcontent) Detect language name from file content using the shebang line (`#!`). Inspects only the first line of `content`. If it begins with `#!`, the interpreter name is extracted and mapped to a language name. Handles common patterns: * `#!/usr/bin/env python3` → `"python"` * `#!/bin/bash` → `"bash"` * `#!/usr/bin/env node` → `"javascript"` The `-S` flag accepted by some `env` implementations is skipped automatically. Version suffixes (e.g. `python3.11`, `ruby3.2`) are stripped before matching. A leading UTF-8 BOM (`U+FEFF`) is skipped before the `#!` check, so a BOM-prefixed script is still detected by its shebang. Returns `null` when content does not start with `#!` (after stripping a leading BOM), the shebang is malformed, or the interpreter is not recognised. **Signature:** ```typescript function detectLanguageFromContent(content: string): string | null ``` **Example:** ```typescript const result = detectLanguageFromContent("value"); ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------- | -------- | ---------------------- | | `content` | `string` | Yes | The content to process | **Returns:** `string | null` *** #### getHighlightsQuery() [Section titled “getHighlightsQuery()”](#gethighlightsquery) Get the highlights query for a language, if bundled. Returns the contents of `highlights.scm` as a static string, or `null` if no highlights query is bundled for this language. **Signature:** ```typescript function getHighlightsQuery(language: string): string | null ``` **Example:** ```typescript const result = getHighlightsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `string | null` *** #### getInjectionsQuery() [Section titled “getInjectionsQuery()”](#getinjectionsquery) Get the injections query for a language, if bundled. Returns the contents of `injections.scm` as a static string, or `null` if no injections query is bundled for this language. **Signature:** ```typescript function getInjectionsQuery(language: string): string | null ``` **Example:** ```typescript const result = getInjectionsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `string | null` *** #### getLocalsQuery() [Section titled “getLocalsQuery()”](#getlocalsquery) Get the locals query for a language, if bundled. Returns the contents of `locals.scm` as a static string, or `null` if no locals query is bundled for this language. **Signature:** ```typescript function getLocalsQuery(language: string): string | null ``` **Example:** ```typescript const result = getLocalsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `string | null` *** #### getTagsQuery() [Section titled “getTagsQuery()”](#gettagsquery) Get the tags query for a language, if bundled. Returns the contents of `tags.scm` as a static string, or `null` if no tags query is bundled for this language. **Signature:** ```typescript function getTagsQuery(language: string): string | null ``` **Example:** ```typescript const result = getTagsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `string | null` *** #### getIndentsQuery() [Section titled “getIndentsQuery()”](#getindentsquery) Get the indents query for a language, if bundled. Returns the contents of `indents.scm` (used for auto-indentation) as a static string, or `null` if no indents query is bundled for this language. **Signature:** ```typescript function getIndentsQuery(language: string): string | null ``` **Example:** ```typescript const result = getIndentsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `string | null` *** #### getFoldsQuery() [Section titled “getFoldsQuery()”](#getfoldsquery) Get the folds query for a language, if bundled. Returns the contents of `folds.scm` (used for code folding) as a static string, or `null` if no folds query is bundled for this language. **Signature:** ```typescript function getFoldsQuery(language: string): string | null ``` **Example:** ```typescript const result = getFoldsQuery("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------- | -------- | ------------ | | `language` | `string` | Yes | The language | **Returns:** `string | null` *** #### getLanguage() [Section titled “getLanguage()”](#getlanguage) Get a tree-sitter `Language` by name using the global registry. Resolves language aliases (e.g., `"shell"` maps to `"bash"`). When the `download` feature is enabled (default), automatically downloads the parser from GitHub releases if not found locally. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.Download` if auto-download fails. **Signature:** ```typescript function getLanguage(name: string): Language ``` **Example:** ```typescript const result = getLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `Language` **Errors:** Throws `Error` with a descriptive message. *** #### getParser() [Section titled “getParser()”](#getparser) Get a `Parser` pre-configured for the given language. This is a convenience function that calls `get_language` and configures a new parser in one step. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language cannot be applied to the parser. **Signature:** ```typescript function getParser(name: string): Parser ``` **Example:** ```typescript const result = getParser("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `Parser` **Errors:** Throws `Error` with a descriptive message. *** #### detectLanguage() [Section titled “detectLanguage()”](#detectlanguage) Detect language name from a file path or extension. This compatibility alias matches the pre-Alef Python binding API. **Signature:** ```typescript function detectLanguage(path: string): string | null ``` **Example:** ```typescript const result = detectLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ---------------- | | `path` | `string` | Yes | Path to the file | **Returns:** `string | null` *** #### availableLanguages() [Section titled “availableLanguages()”](#availablelanguages) List all available language names (sorted, deduplicated, includes aliases). Returns names of both statically compiled and dynamically loadable languages, plus any configured aliases. **Signature:** ```typescript function availableLanguages(): Array ``` **Example:** ```typescript const result = availableLanguages(); ``` **Returns:** `Array` *** #### hasLanguage() [Section titled “hasLanguage()”](#haslanguage) Check if a language is available by name or alias. Returns `true` if the language can be loaded (statically compiled, dynamically available, or a known alias for one of these). **Signature:** ```typescript function hasLanguage(name: string): boolean ``` **Example:** ```typescript const result = hasLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `boolean` *** #### languageCount() [Section titled “languageCount()”](#languagecount) Return the number of available languages. Includes statically compiled languages, dynamically loadable languages, and aliases. **Signature:** ```typescript function languageCount(): number ``` **Example:** ```typescript const result = languageCount(); ``` **Returns:** `number` *** #### process() [Section titled “process()”](#process) Process source code and extract file intelligence using the global registry. Parses the source with tree-sitter and extracts metrics, structure, imports, exports, comments, docstrings, symbols, diagnostics, and/or chunks based on the flags set in `ProcessConfig`. **Errors:** Returns `Error.InvalidRange` if the config carries a zero-valued limit or the source exceeds `ProcessConfig.max_source_bytes`, `Error.ParseTimeout` if the parse exceeds `ProcessConfig.parse_timeout_ms`, `Error.LanguageNotFound` if the language is unknown, or `Error.ParseFailed` if parsing yields no tree. **Signature:** ```typescript function process(source: string, config: ProcessConfig): ProcessResult ``` **Example:** ```typescript const result = process("value", new ProcessConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `string` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Throws `Error` with a descriptive message. *** #### prefetch() [Section titled “prefetch()”](#prefetch) Prefetch grammars by loading each into the registry. Without the `download` feature there is no network step — every requested language must already be statically compiled or present on disk. **Errors:** Returns `Error.LanguageNotFound` if a requested language is not available. **Signature:** ```typescript function prefetch(languages: Array): void ``` **Example:** ```typescript prefetch([]); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | --------------- | -------- | ------------- | | `languages` | `Array` | Yes | The languages | **Returns:** No return value. **Errors:** Throws `Error` with a descriptive message. *** ### Types [Section titled “Types”](#types) #### ByteRange [Section titled “ByteRange”](#byterange) A byte range — start (inclusive) to end (exclusive). | Field | Type | Default | Description | | ------- | -------- | ------- | ---------------------------- | | `start` | `number` | — | Inclusive start byte offset. | | `end` | `number` | — | Exclusive end byte offset. | *** #### ChunkContext [Section titled “ChunkContext”](#chunkcontext) Metadata for a single chunk of source code. | Field | Type | Default | Description | | ---------------- | ---------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `string` | — | Language name used to parse this chunk. | | `chunkIndex` | `number` | — | Zero-indexed position of this chunk within the file’s chunk list. | | `totalChunks` | `number` | — | Total number of chunks the file was split into. | | `nodeTypes` | `Array` | `[]` | Tree-sitter node kinds that appear at the top level of this chunk. | | `contextPath` | `Array` | `[]` | Hierarchical path of enclosing structural items (e.g., `["MyClass", "my_method"]`). | | `symbolsDefined` | `Array` | `[]` | Names of symbols defined within this chunk. | | `comments` | `Array` | `[]` | Comments contained within this chunk. | | `docstrings` | `Array` | `[]` | Docstrings contained within this chunk. Populated only for Python — the same language for which `ProcessResult.docstrings` is populated, and by the same classifier. Always empty for every other language. | | `hasErrorNodes` | `boolean` | — | Whether this chunk contains any tree-sitter error nodes. | *** #### CodeChunk [Section titled “CodeChunk”](#codechunk) A chunk of source code with rich metadata. | Field | Type | Default | Description | | ----------- | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `content` | `string` | — | The raw source text of this chunk. | | `startByte` | `number` | — | Inclusive start byte offset of this chunk in the original source. | | `endByte` | `number` | — | Exclusive end byte offset of this chunk in the original source. | | `startLine` | `number` | — | Zero-indexed start line of this chunk. | | `endLine` | `number` | — | Zero-indexed row of the last byte actually included in this chunk (inclusive — the same row a `Span.end_line` would report for a node ending on that byte). Computed the same way regardless of whether the source has a trailing newline: it is always the row of `end_byte - 1`, never a phantom row past the file’s real content. | | `metadata` | `ChunkContext` | — | Contextual metadata about this chunk. | *** #### CommentInfo [Section titled “CommentInfo”](#commentinfo) A comment extracted from source code. | Field | Type | Default | Description | | ---------------- | ---------------- | ------------------ | ----------------------------------------------------------------- | | `text` | `string` | — | The raw text content of the comment. | | `kind` | `CommentKind` | `CommentKind.Line` | The kind of comment (line, block, or doc). | | `span` | `Span` | — | Source span covering the comment. | | `associatedNode` | `string \| null` | `null` | Name of the syntax node this comment is directly associated with. | *** #### DataAttribute [Section titled “DataAttribute”](#dataattribute) An XML-style attribute attached to an `Element` node. Populated only for `DataNodeKind.Element`; always empty for `KeyValue` and `Sequence` nodes. | Field | Type | Default | Description | | ------- | -------- | ------- | --------------------------------------------------------------- | | `name` | `string` | — | Attribute name (e.g. `"class"`, `"href"`). | | `value` | `string` | — | Attribute value as a raw string (quotes stripped). | | `span` | `Span` | — | Source span covering the entire `name="value"` attribute token. | *** #### DataNode [Section titled “DataNode”](#datanode) A node in the hierarchical data tree produced by data-format extraction. When `ProcessConfig.data_extraction` is `true`, `ProcessResult.data` is populated with a root `DataNode` whose `children` mirror the structure of the parsed file. The `kind` field determines which other fields are meaningful: | `kind` | `key` | `value` | `attributes` | `children` | | ---------- | ------------------------- | ------------ | ------------ | -------------- | | `KeyValue` | key / mapping key / index | leaf value | empty | nested map | | `Element` | XML tag name | text content | XML attrs | child elements | | `Sequence` | positional index (`"0"`) | leaf value | empty | sub-items | | Field | Type | Default | Description | | ------------ | ---------------------- | ----------------------- | ----------------------------------------------------------------------------------------------------- | | `kind` | `DataNodeKind` | `DataNodeKind.KeyValue` | Whether this node is a key/value pair, XML element, or sequence item. | | `key` | `string \| null` | `null` | Key, attribute name, tag name, or positional index (`"0"`, `"1"`, …). `null` at the document root. | | `value` | `string \| null` | `null` | Leaf scalar value, if any. `null` for containers (objects, arrays, XML elements with child elements). | | `attributes` | `Array` | `[]` | Attributes on element-shape nodes (XML `STag` attributes). Empty for all other kinds. | | `children` | `Array` | `[]` | Children for nested containers and XML element bodies. | | `span` | `Span` | — | Source span covering this node in the original source file. | *** #### Diagnostic [Section titled “Diagnostic”](#diagnostic) A diagnostic (syntax error, missing node, etc.) from parsing. | Field | Type | Default | Description | | ---------- | -------------------- | -------------------------- | ---------------------------------------------- | | `message` | `string` | — | Human-readable description of the diagnostic. | | `severity` | `DiagnosticSeverity` | `DiagnosticSeverity.Error` | Severity of the diagnostic. | | `span` | `Span` | — | Source span where the diagnostic was detected. | *** #### DocSection [Section titled “DocSection”](#docsection) A section within a docstring (e.g., Args, Returns, Raises). | Field | Type | Default | Description | | ------------- | ---------------- | ------- | ------------------------------------------------------- | | `kind` | `string` | — | Section kind (e.g., `"args"`, `"returns"`, `"raises"`). | | `name` | `string \| null` | `null` | Parameter or return value name, if applicable. | | `description` | `string` | — | Description text for this section. | *** #### DocstringInfo [Section titled “DocstringInfo”](#docstringinfo) A docstring extracted from source code. | Field | Type | Default | Description | | ---------------- | ------------------- | ----------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | `string` | — | The raw text of the docstring. | | `format` | `DocstringFormat` | `DocstringFormat.PythonTripleQuote` | The docstring format (Python, JSDoc, Rustdoc, etc.). | | `span` | `Span` | — | Source span covering the docstring. | | `associatedItem` | `string \| null` | `null` | Name of the item this docstring documents. | | `parsedSections` | `Array` | `[]` | Parsed sections of the docstring (Args, Returns, Raises, etc.). **Reserved: not yet populated.** Always empty, for every `DocstringFormat`. Parsing a docstring body into sections requires implementing each convention’s own layout (Google/NumPy/reST style for Python, `@param`/`@returns` for JSDoc/Javadoc, and so on), which no extractor here does yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | *** #### ExportInfo [Section titled “ExportInfo”](#exportinfo) An export statement extracted from source code. | Field | Type | Default | Description | | ------ | ------------ | ------------------ | -------------------------------------------------- | | `name` | `string` | — | The exported name. | | `kind` | `ExportKind` | `ExportKind.Named` | The kind of export (named, default, or re-export). | | `span` | `Span` | — | Source span covering the export statement. | *** #### FileMetrics [Section titled “FileMetrics”](#filemetrics) Aggregate metrics for a source file. | Field | Type | Default | Description | | -------------- | -------- | ------- | -------------------------------------------------------------- | | `totalLines` | `number` | — | Total number of lines (including blank and comment lines). | | `codeLines` | `number` | — | Number of lines containing non-blank, non-comment source code. | | `commentLines` | `number` | — | Number of lines that are entirely comments. | | `blankLines` | `number` | — | Number of blank (whitespace-only) lines. | | `totalBytes` | `number` | — | Total byte length of the source file. | | `nodeCount` | `number` | — | Total number of nodes in the syntax tree. | | `errorCount` | `number` | — | Number of error nodes in the syntax tree (parse errors). | | `maxDepth` | `number` | — | Maximum nesting depth reached in the syntax tree. | *** #### ImportInfo [Section titled “ImportInfo”](#importinfo) An import statement extracted from source code. | Field | Type | Default | Description | | ------------ | ---------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `source` | `string` | — | The module or path being imported from. | | `items` | `Array` | `[]` | Specific names imported from the source module. For `import a, b` / `from m import a, b`, every entry’s base name (never the alias). For a JavaScript/TypeScript named-imports clause (`import { a, b as c } from 'm'`), every specifier’s original name. Populated for Python and JavaScript/TypeScript only. Always empty for every other language this library recognises import statements for — Rust, Go, Java, Kotlin, and Elixir (`import`/`alias`/`require`/`use`) — and for a JS/TS namespace import (`import * as ns`) or default import (`import x from 'm'`), neither of which names individual items. | | `alias` | `string \| null` | `null` | Alias assigned to the import (e.g., `import numpy as np`). Populated for Python’s single-name form (`import numpy as np`, `from m import a as b`) and JavaScript/TypeScript’s namespace form (`import * as ns from 'm'`) or a named-imports clause naming exactly one specifier (`import { a as b } from 'm'`). `null` for Rust, Go, Java, Kotlin, and Elixir (which has its own `as:` alias option on `alias` directives, not yet extracted here) — and for a Python statement that aliases several names at once (`import os, sys as s`), where there is no single alias to report for the statement as a whole, so only `items` is populated for it. | | `isWildcard` | `boolean` | — | Whether this is a wildcard import (e.g., `import *` or `use foo.*`). Detected from the syntax tree — a dedicated wildcard node (`wildcard_import` in Python, `use_wildcard` in Rust) or a bare `*` token outside of string-literal content — not by searching the import’s source text for a `*` character, so a glob in an import path string (`import a from './glob*.js'`) is not mistaken for one. | | `span` | `Span` | — | Source span covering the import statement. | *** #### Language [Section titled “Language”](#language) *** #### LanguageRegistry [Section titled “LanguageRegistry”](#languageregistry) Thread-safe registry of tree-sitter language parsers. Manages both statically compiled and dynamically loaded language grammars. Use `LanguageRegistry.new()` for the default registry, or access the global instance via the module-level convenience functions (`get_language`, `available_languages`, etc.). ##### Methods [Section titled “Methods”](#methods) ###### new() [Section titled “new()”](#new) Create a new registry populated with all statically compiled languages. When the `dynamic-loading` feature is enabled, the registry also knows about dynamically loadable grammars and will load them on demand. **Signature:** ```typescript static new(): LanguageRegistry ``` **Example:** ```typescript const result = LanguageRegistry.new(); ``` **Returns:** `LanguageRegistry` ###### getLanguage() [Section titled “getLanguage()”](#getlanguage-1) Get a tree-sitter `Language` by name. Resolves aliases (e.g., `"shell"` -> `"bash"`, `"makefile"` -> `"make"`), then looks up the language in the static table. When the `dynamic-loading` feature is enabled, falls back to loading a shared library on demand. **Errors:** Returns `Error.LanguageNotFound` if the name (after alias resolution) does not match any known grammar. **Signature:** ```typescript getLanguage(name: string): Language ``` **Example:** ```typescript const result = instance.getLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `Language` **Errors:** Throws `Error` with a descriptive message. ###### availableLanguages() [Section titled “availableLanguages()”](#availablelanguages-1) List all available language names, sorted and deduplicated. Includes statically compiled languages, dynamically loadable languages (if the `dynamic-loading` feature is enabled), and all configured aliases. **Signature:** ```typescript availableLanguages(): Array ``` **Example:** ```typescript const result = instance.availableLanguages(); ``` **Returns:** `Array` ###### hasParser() [Section titled “hasParser()”](#hasparser) Check whether this language can be parsed right now, without downloading. Resolves aliases, then answers from exactly the lookup `get_language` performs: the statically compiled table, the already-loaded dynamic grammars, and the parser shared libraries present in the primary and extra (download-cache) library directories. It never performs network I/O. A previous implementation consulted only the statically compiled table. That table is empty in every build that does not set `TSLP_LANGUAGES`, so the function answered `false` for languages this registry parses perfectly well. Contrast `has_language`, which is also `true` for a grammar that is merely *known to the manifest* and would have to be downloaded first. The pair distinguishes “we can parse it offline, now” from “we recognise the name”. The first `true` answer for a dynamic grammar loads its shared library: loading is the only way to know the grammar is usable, since a truncated or wrong-architecture library exists on disk but cannot parse. Loads are cached process-wide, so repeat calls are cheap. **Signature:** ```typescript hasParser(name: string): boolean ``` **Example:** ```typescript const result = instance.hasParser("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `boolean` ###### hasLanguage() [Section titled “hasLanguage()”](#haslanguage-1) Check whether a language is available by name or alias. Returns `true` if the language can be loaded, either from the static table or from a dynamic library on disk. Every branch is one more way to answer `true`, so they are ordered cheapest-first and the filesystem is only consulted once every in-memory source has said no. Probing the loaded-grammar map and the manifest ahead of the `stat` calls is what keeps this off the syscall path for the languages a process actually uses. **Signature:** ```typescript hasLanguage(name: string): boolean ``` **Example:** ```typescript const result = instance.hasLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `boolean` ###### languageCount() [Section titled “languageCount()”](#languagecount-1) Return the total number of available languages (including aliases). Counts the same set `available_languages` lists, without materialising or sorting it. **Signature:** ```typescript languageCount(): number ``` **Example:** ```typescript const result = instance.languageCount(); ``` **Returns:** `number` ###### process() [Section titled “process()”](#process-1) Parse source code and extract file intelligence based on config in a single pass. **Errors:** Returns `Error.InvalidRange` if the config is invalid (see `ProcessConfig.validate`) or if the source exceeds the configured `max_source_bytes`; `Error.LanguageNotFound` if the language is unknown; or `Error.ParseFailed` if parsing produces no tree. **Signature:** ```typescript process(source: string, config: ProcessConfig): ProcessResult ``` **Example:** ```typescript const result = instance.process("value", new ProcessConfig()); ``` **Parameters:** | Name | Type | Required | Description | | -------- | --------------- | -------- | ------------------------- | | `source` | `string` | Yes | The source | | `config` | `ProcessConfig` | Yes | The configuration options | **Returns:** `ProcessResult` **Errors:** Throws `Error` with a descriptive message. *** #### Node [Section titled “Node”](#node) A single syntax node within a `Tree`. Nodes hold a strong reference to their parent tree so they remain valid regardless of how the tree is moved or stored at the FFI boundary. ##### Methods [Section titled “Methods”](#methods-1) ###### kind() [Section titled “kind()”](#kind) Return the node’s kind name (e.g. `"function_definition"`). **Signature:** ```typescript kind(): string ``` **Example:** ```typescript const result = instance.kind(); ``` **Returns:** `string` ###### kindId() [Section titled “kindId()”](#kindid) Return the node’s numeric kind ID. Tree-sitter assigns a stable `u16` ID to every node kind in a grammar (e.g. `"function_definition" → 42`). Comparing `kind_id()` is cheaper than comparing the string `kind()` in tight AST loops. **Signature:** ```typescript kindId(): number ``` **Example:** ```typescript const result = instance.kindId(); ``` **Returns:** `number` ###### startByte() [Section titled “startByte()”](#startbyte) Return the inclusive start byte offset of this node. **Signature:** ```typescript startByte(): number ``` **Example:** ```typescript const result = instance.startByte(); ``` **Returns:** `number` ###### endByte() [Section titled “endByte()”](#endbyte) Return the exclusive end byte offset of this node. **Signature:** ```typescript endByte(): number ``` **Example:** ```typescript const result = instance.endByte(); ``` **Returns:** `number` ###### byteRange() [Section titled “byteRange()”](#byterange-1) Return the node’s byte range as a `ByteRange`. Callers should slice their own source bytes — this is a zero-copy text accessor. **Signature:** ```typescript byteRange(): ByteRange ``` **Example:** ```typescript const result = instance.byteRange(); ``` **Returns:** `ByteRange` ###### startPosition() [Section titled “startPosition()”](#startposition) Return the start `Point` (row, column). **Signature:** ```typescript startPosition(): Point ``` **Example:** ```typescript const result = instance.startPosition(); ``` **Returns:** `Point` ###### endPosition() [Section titled “endPosition()”](#endposition) Return the end `Point` (row, column). **Signature:** ```typescript endPosition(): Point ``` **Example:** ```typescript const result = instance.endPosition(); ``` **Returns:** `Point` ###### isNamed() [Section titled “isNamed()”](#isnamed) True when this node is named (not punctuation/whitespace). **Signature:** ```typescript isNamed(): boolean ``` **Example:** ```typescript const result = instance.isNamed(); ``` **Returns:** `boolean` ###### isError() [Section titled “isError()”](#iserror) True when this is an error node. **Signature:** ```typescript isError(): boolean ``` **Example:** ```typescript const result = instance.isError(); ``` **Returns:** `boolean` ###### isMissing() [Section titled “isMissing()”](#ismissing) True when this is a missing-token node. **Signature:** ```typescript isMissing(): boolean ``` **Example:** ```typescript const result = instance.isMissing(); ``` **Returns:** `boolean` ###### isExtra() [Section titled “isExtra()”](#isextra) True when this is an “extra” node (e.g. a comment). **Signature:** ```typescript isExtra(): boolean ``` **Example:** ```typescript const result = instance.isExtra(); ``` **Returns:** `boolean` ###### hasError() [Section titled “hasError()”](#haserror) True when this node or any descendant is an error. **Signature:** ```typescript hasError(): boolean ``` **Example:** ```typescript const result = instance.hasError(); ``` **Returns:** `boolean` ###### parent() [Section titled “parent()”](#parent) Return this node’s parent, if any. **Signature:** ```typescript parent(): Node | null ``` **Example:** ```typescript const result = instance.parent(); ``` **Returns:** `Node | null` ###### child() [Section titled “child()”](#child) Return the i-th child of this node, if any. **Signature:** ```typescript child(index: number): Node | null ``` **Example:** ```typescript const result = instance.child(42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | -------- | -------- | ----------- | | `index` | `number` | Yes | The index | **Returns:** `Node | null` ###### childCount() [Section titled “childCount()”](#childcount) Total number of children (including unnamed). **Signature:** ```typescript childCount(): number ``` **Example:** ```typescript const result = instance.childCount(); ``` **Returns:** `number` ###### namedChild() [Section titled “namedChild()”](#namedchild) Return the i-th named child of this node, if any. **Signature:** ```typescript namedChild(index: number): Node | null ``` **Example:** ```typescript const result = instance.namedChild(42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | -------- | -------- | ----------- | | `index` | `number` | Yes | The index | **Returns:** `Node | null` ###### namedChildCount() [Section titled “namedChildCount()”](#namedchildcount) Number of named children of this node. **Signature:** ```typescript namedChildCount(): number ``` **Example:** ```typescript const result = instance.namedChildCount(); ``` **Returns:** `number` ###### childByFieldName() [Section titled “childByFieldName()”](#childbyfieldname) Look up a child by its grammar-defined field name. **Signature:** ```typescript childByFieldName(name: string): Node | null ``` **Example:** ```typescript const result = instance.childByFieldName("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** `Node | null` ###### toSexp() [Section titled “toSexp()”](#tosexp) Return the S-expression form of this node’s subtree. **Signature:** ```typescript toSexp(): string ``` **Example:** ```typescript const result = instance.toSexp(); ``` **Returns:** `string` ###### walk() [Section titled “walk()”](#walk) Return a `TreeCursor` positioned at this node. **Signature:** ```typescript walk(): TreeCursor ``` **Example:** ```typescript const result = instance.walk(); ``` **Returns:** `TreeCursor` *** #### PackConfig [Section titled “PackConfig”](#packconfig) Configuration for the tree-sitter language pack. Controls cache directory and which languages to pre-download. Can be loaded from a TOML file, constructed programmatically, or passed as a dict/object from language bindings. | Field | Type | Default | Description | | ----------- | ----------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cacheDir` | `string \| null` | `null` | Override the BASE directory the parser cache lives under. This is a base, not the final library path: the crate appends `tree-sitter-language-pack/v{version}/libs` to it, exactly as it does to the platform default. So `cache_dir = "/tmp/my-parsers"` resolves to `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`. The suffix is not cosmetic. It keeps the whole cache tree — manifest, bundles and lock file included — inside a directory this library owns and versions. Earlier releases used this path verbatim, which put those files in the configured directory’s PARENT and let a cache built by one crate version be reused by another. Default base: the platform cache dir, e.g. `~/.cache` on Linux. | | `languages` | `Array \| null` | `[]` | Languages to pre-download on init. Each entry is a language name (e.g. `"python"`, `"rust"`). | | `groups` | `Array \| null` | `[]` | Language groups to pre-download. Group names come from the remote manifest, so the valid set is not fixed by this library; the published manifest currently defines only `"all"`. Call `manifest_groups` to enumerate them. An unknown name makes `init` fail. | *** #### Parser [Section titled “Parser”](#parser) A tree-sitter parser configured for one language at a time. ##### Methods [Section titled “Methods”](#methods-2) ###### new() [Section titled “new()”](#new-1) Construct a new parser with no language set and no parse limits. Call `Parser.set_language` before parsing. Limits are opt-in via `set_max_source_bytes` and `set_parse_timeout_ms`; both default to unbounded so that existing callers are unaffected. **Signature:** ```typescript static new(): Parser ``` **Example:** ```typescript const result = Parser.new(); ``` **Returns:** `Parser` ###### setMaxSourceBytes() [Section titled “setMaxSourceBytes()”](#setmaxsourcebytes) Refuse to parse sources longer than `max_bytes`. `null` (the default) means no limit. Over-limit input makes `parse` and `parse_bytes` return `null` after emitting a `WARN`; input is never silently truncated. See `RECOMMENDED_MAX_SOURCE_BYTES`. **Signature:** ```typescript setMaxSourceBytes(maxBytes: number): void ``` **Example:** ```typescript instance.setMaxSourceBytes(42); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | ---------------- | -------- | ------------- | | `maxBytes` | `number \| null` | No | The max bytes | **Returns:** No return value. ###### setParseTimeoutMs() [Section titled “setParseTimeoutMs()”](#setparsetimeoutms) Cancel a parse that exceeds `timeout_ms` milliseconds of wall clock. `null` (the default) means no budget. Cancellation runs through tree-sitter’s parse progress callback, so it is granular to that callback’s interval rather than exact. See `RECOMMENDED_PARSE_TIMEOUT_MS`. **Signature:** ```typescript setParseTimeoutMs(timeoutMs: number): void ``` **Example:** ```typescript instance.setParseTimeoutMs(42); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | ---------------- | -------- | -------------- | | `timeoutMs` | `number \| null` | No | The timeout ms | **Returns:** No return value. ###### setLanguage() [Section titled “setLanguage()”](#setlanguage) Configure the parser to use the language identified by name (e.g. `"python"`). Resolves the language through the global registry — auto-downloading if necessary, when the `download` feature is enabled. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language ABI is incompatible. **Signature:** ```typescript setLanguage(name: string): void ``` **Example:** ```typescript instance.setLanguage("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------- | -------- | ----------- | | `name` | `string` | Yes | The name | **Returns:** No return value. **Errors:** Throws `Error` with a descriptive message. ###### parse() [Section titled “parse()”](#parse) Parse a UTF-8 source string. Returns `null` if no language is set, if the parse was cancelled by the configured timeout, or if the source exceeds the configured size limit. Each non-parse outcome is logged, so an empty result is never silent. ###### Concurrency [Section titled “Concurrency”](#concurrency) Parsing runs fully in parallel across threads for almost every language — no lock is taken. The exception is the small set of grammars whose external scanner keeps mutable process-global state (currently just `properties`): parses of that language are serialized against each other through an internal per-language lock, so that concurrent threads can’t corrupt shared scanner state. Every other language is unaffected by that lock and never waits on it. **Signature:** ```typescript parse(source: string): Tree | null ``` **Example:** ```typescript const result = instance.parse("value"); ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------- | -------- | ----------- | | `source` | `string` | Yes | The source | **Returns:** `Tree | null` ###### parseBytes() [Section titled “parseBytes()”](#parsebytes) Parse a raw byte slice. Same outcomes as `parse`, including the concurrency behaviour documented there. **Signature:** ```typescript parseBytes(source: Buffer): Tree | null ``` **Example:** ```typescript const result = instance.parseBytes(new Uint8Array([100, 97, 116, 97])); ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------- | -------- | ----------- | | `source` | `Buffer` | Yes | The source | **Returns:** `Tree | null` ###### reset() [Section titled “reset()”](#reset) Reset internal state. The next call to `parse` will not be incremental. **Signature:** ```typescript reset(): void ``` **Example:** ```typescript instance.reset(); ``` **Returns:** No return value. *** #### Point [Section titled “Point”](#point) A source position — row + column, zero-indexed. | Field | Type | Default | Description | | -------- | -------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `row` | `number` | — | Zero-indexed row number. | | `column` | `number` | — | Zero-indexed column, counted in **bytes** from the start of the row. This is `tree_sitter.Point.column` verbatim, and tree-sitter defines it as a byte offset — not characters, and not UTF-16 code units. Measured on a row of the form `x = ''` where `` is a single 4-byte character (an emoji), the string node reports columns `4..10`, identical to its byte range; the character columns would be `4..7` and the UTF-16 columns `4..8`. Anything that builds LSP positions (UTF-16) or editor caret columns (characters) from this field is silently wrong on every row containing a non-ASCII byte, and must re-measure the row against the source text instead. Earlier releases documented this field as UTF-16 code units; that was never what the value contained. | *** #### ProcessConfig [Section titled “ProcessConfig”](#processconfig) Configuration for the `process()` function. Controls which analysis features are enabled and whether chunking is performed. | Field | Type | Default | Description | | ---------------- | ---------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `string` | `""` | Language name (required). | | `structure` | `boolean` | `true` | Extract structural items (functions, classes, etc.). Default: true. | | `imports` | `boolean` | `true` | Extract import statements. Default: true. | | `exports` | `boolean` | `true` | Extract export statements. Default: true. | | `comments` | `boolean` | `false` | Extract comments. Default: false. | | `docstrings` | `boolean` | `false` | Extract docstrings. Default: false. | | `symbols` | `boolean` | `false` | Extract symbol definitions. Default: false. | | `diagnostics` | `boolean` | `false` | Include parse diagnostics. Default: false. | | `chunkMaxSize` | `number \| null` | `null` | Maximum chunk size in bytes. `null` disables chunking. `Some(0)` is rejected by `ProcessConfig.validate` with `Error.InvalidRange`. A zero-sized chunk limit previously produced an empty chunk list and silently discarded the whole source; use `null` to mean “do not chunk”. | | `dataExtraction` | `boolean` | `false` | Extract hierarchical key/value data tree from data-format files. Default: false. When `true`, `ProcessResult.data` is populated with a `DataNode` tree for supported languages: JSON, YAML, TOML, `.properties`, HCL/HOCON, INI, editorconfig, KDL, CUE, CSV, PSV, PO, nginx config, Caddy config, XML, and DTD. For languages outside this set the field is left as `null`. | | `maxSourceBytes` | `number \| null` | `null` | Reject source longer than this many bytes instead of parsing it. Default: `null` (unbounded). Tree-sitter allocates and walks proportionally to input size, so an unbounded parse of attacker-supplied input is a denial-of-service vector. The default stays unbounded for backward compatibility; services handling untrusted input should opt in, e.g. with `RECOMMENDED_MAX_SOURCE_BYTES`. Exceeding the limit fails the call with `Error.InvalidRange` — the source is never silently truncated. | | `parseTimeoutMs` | `number \| null` | `null` | Wall-clock budget for the parse step, in milliseconds. Default: `null` (no timeout). Enforced through tree-sitter’s parse progress callback, which the parser invokes periodically; cancellation is therefore granular to that callback interval rather than exact. A parse that exceeds the budget fails with `Error.ParseTimeout`. | *** #### ProcessResult [Section titled “ProcessResult”](#processresult) Complete analysis result from processing a source file. Contains metrics, structural analysis, imports/exports, comments, docstrings, symbols, diagnostics, and optionally chunked code segments. Fields are populated based on the `ProcessConfig` flags. | Field | Type | Default | Description | | ------------- | ---------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `string` | — | The language name used to parse the source file. | | `metrics` | `FileMetrics` | — | File-level metrics (line counts, byte size, error count). | | `structure` | `Array` | `[]` | Top-level structural items (functions, classes, etc.). | | `imports` | `Array` | `[]` | Import statements extracted from the source. | | `exports` | `Array` | `[]` | Export statements extracted from the source. | | `comments` | `Array` | `[]` | Comments extracted from the source. | | `docstrings` | `Array` | `[]` | Docstrings extracted from the source. | | `symbols` | `Array` | `[]` | Symbol definitions (variables, types, functions) extracted from the source. | | `diagnostics` | `Array` | `[]` | Parse diagnostics (syntax errors, missing nodes) from tree-sitter. | | `chunks` | `Array` | `[]` | Syntax-aware code chunks produced when chunking is enabled. | | `data` | `DataNode \| null` | `null` | Hierarchical data tree extracted when `config.data_extraction` is `true`. Populated for supported data-format languages (JSON, YAML, TOML, properties, HCL, INI, XML, CSV, and more). `null` when `data_extraction` is `false` (the default) or when the language is not a recognised data format. See `DataNode` for the shape of the returned tree. | *** #### Span [Section titled “Span”](#span) Byte and line/column range in source code. Represents both byte offsets (for slicing) and human-readable line/column positions (for display and diagnostics). | Field | Type | Default | Description | | ------------- | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `startByte` | `number` | — | Inclusive start byte offset in the source. | | `endByte` | `number` | — | Exclusive end byte offset in the source. | | `startLine` | `number` | — | Zero-indexed line number of the span’s start. | | `startColumn` | `number` | — | Zero-indexed column of the span’s start, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | | `endLine` | `number` | — | Zero-indexed line number of the span’s end. | | `endColumn` | `number` | — | Zero-indexed column of the span’s end, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | *** #### StructureItem [Section titled “StructureItem”](#structureitem) A structural item (function, class, struct, etc.) in source code. | Field | Type | Default | Description | | ------------ | ---------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `kind` | `StructureKind` | `StructureKind.Function` | The kind of structural item. | | `name` | `string \| null` | `null` | The declared name of the item, if present. | | `visibility` | `string \| null` | `null` | Visibility modifier (e.g., `"pub"`, `"public"`, `"private"`). | | `span` | `Span` | — | Source span covering the entire item declaration. | | `children` | `Array` | `[]` | Nested structural items (e.g., methods within a class). | | `decorators` | `Array` | `[]` | Decorator or attribute names applied to the item. **Reserved: not yet populated.** Always empty, for every language. Recognising a decorator requires per-language grammar knowledge (a Python `decorated_definition` wrapper, Java/C# annotations, Rust attributes each have a different shape), which no extractor here implements yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | | `docComment` | `string \| null` | `null` | Documentation comment attached to the item, if any. The text of the comment (or run of comments) immediately preceding the item, with no blank line in between, when that comment is classified as a doc comment. Multiple adjacent single-line doc comments (Rust `///`) are joined with `\n` in source order. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`). `null` for every other language, and for a preceding comment that is not in doc-comment form (a plain `#` comment in Python, Ruby, or Elixir) — Python’s docstring convention is captured separately, as `DocstringInfo`, not through this field. | | `signature` | `string \| null` | `null` | Full signature text of the item (e.g., function parameters and return type). The item’s own source text from its start up to the start of its body (see `StructureItem.body_span`), trimmed of trailing whitespace — for example `fn add(a: i32, b: i32) -> i32` for a Rust function whose body is `{ a + b }`. `null` only when that text is empty, which does not happen for any item `StructureKind` currently reports. Populated for every language and kind this library extracts structure for, since it is derived from `body_span`’s boundary rather than per-language syntax. | | `bodySpan` | `Span \| null` | `null` | Source span covering only the body of the item, if distinct from the declaration. | *** #### SymbolInfo [Section titled “SymbolInfo”](#symbolinfo) A symbol (variable, function, type, etc.) extracted from source code. | Field | Type | Default | Description | | ---------------- | ---------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `string` | — | The name of the symbol. | | `kind` | `SymbolKind` | `SymbolKind.Variable` | The kind of symbol (variable, function, class, etc.). | | `span` | `Span` | — | Source span covering the symbol definition. | | `typeAnnotation` | `string \| null` | `null` | Explicit type annotation, if present in the source. | | `doc` | `string \| null` | `null` | Documentation comment immediately preceding this symbol, resolved by the same walk `StructureItem.doc_comment` uses (see `doc_comment_at`) — never hard-coded `null`. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`) — the languages whose comment classification recognizes a doc-kind comment. `null` for every other language (e.g. Python, Go, Ruby, which have no doc-kind comment classification), and also `null` when a symbol in a supported language simply has no doc comment immediately above it. | *** #### Tree [Section titled “Tree”](#tree) A parsed syntax tree. Cheap to clone (refcount bump). ##### Methods [Section titled “Methods”](#methods-3) ###### rootNode() [Section titled “rootNode()”](#rootnode) Return the root `Node` of this tree. **Signature:** ```typescript rootNode(): Node ``` **Example:** ```typescript const result = instance.rootNode(); ``` **Returns:** `Node` ###### walk() [Section titled “walk()”](#walk-1) Return a `TreeCursor` positioned at the root. **Signature:** ```typescript walk(): TreeCursor ``` **Example:** ```typescript const result = instance.walk(); ``` **Returns:** `TreeCursor` *** #### TreeCursor [Section titled “TreeCursor”](#treecursor) A cursor for traversing a `Tree`. ##### Methods [Section titled “Methods”](#methods-4) ###### node() [Section titled “node()”](#node-1) Return the `Node` at the cursor’s current position. **Signature:** ```typescript node(): Node ``` **Example:** ```typescript const result = instance.node(); ``` **Returns:** `Node` ###### gotoFirstChild() [Section titled “gotoFirstChild()”](#gotofirstchild) Move the cursor to the first child of the current node. Returns `true` if a child existed. **Signature:** ```typescript gotoFirstChild(): boolean ``` **Example:** ```typescript const result = instance.gotoFirstChild(); ``` **Returns:** `boolean` ###### gotoParent() [Section titled “gotoParent()”](#gotoparent) Move the cursor to the parent of the current node. Returns `true` if a parent existed. **Signature:** ```typescript gotoParent(): boolean ``` **Example:** ```typescript const result = instance.gotoParent(); ``` **Returns:** `boolean` ###### gotoNextSibling() [Section titled “gotoNextSibling()”](#gotonextsibling) Move the cursor to the next sibling of the current node. Returns `true` if a sibling existed. **Signature:** ```typescript gotoNextSibling(): boolean ``` **Example:** ```typescript const result = instance.gotoNextSibling(); ``` **Returns:** `boolean` ###### fieldName() [Section titled “fieldName()”](#fieldname) Return the field name for the current node, if any. **Signature:** ```typescript fieldName(): string | null ``` **Example:** ```typescript const result = instance.fieldName(); ``` **Returns:** `string | null` *** ### Enums [Section titled “Enums”](#enums) #### DataNodeKind [Section titled “DataNodeKind”](#datanodekind) The kind of a data node extracted from a data-format file. Classifies each node in the hierarchical `DataNode` tree returned when `data_extraction` is enabled on `ProcessConfig`. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract) Unit variants serialize as a bare string (`"KeyValue"`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ---------- | -------------------------------------------------------------------------------------------------------------------- | | `KeyValue` | A key/value pair or mapping (json/toml/properties/yaml/hcl/cue/kdl pair, or a wrapper “object”/“mapping” container). | | `Element` | An XML element with a tag name in `key` and attributes in `attributes`. | | `Sequence` | A positional sequence item (JSON array element, YAML block sequence item, CSV/PSV row or cell). | *** #### StructureKind [Section titled “StructureKind”](#structurekind) The kind of structural item found in source code. Categorizes top-level and nested declarations such as functions, classes, structs, enums, traits, and more. Use `Other` for language-specific constructs that do not fit a standard category. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-1) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | ---------------------------------------------------------------------------------------------- | | `Function` | A free-standing or associated function. | | `Method` | A method defined inside a class, struct, trait, or impl block. | | `Class` | A class definition. | | `Struct` | A struct definition. | | `Interface` | An interface or protocol definition. | | `Enum` | An enum definition. | | `Module` | A module or package declaration. | | `Trait` | A trait definition. | | `Impl` | An impl block (Rust) or similar implementation block. | | `Namespace` | A namespace declaration. | | `Other` | A language-specific construct that does not fit any standard category. — Fields: `0`: `string` | *** #### CommentKind [Section titled “CommentKind”](#commentkind) The kind of a comment found in source code. Distinguishes between single-line comments, block (multi-line) comments, and documentation comments. | Value | Description | | ------- | --------------------------------------------------------------------- | | `Line` | A single-line comment (e.g., `// ...` or `# ...`). | | `Block` | A block or multi-line comment using slash-star delimiters. | | `Doc` | A documentation comment such as `/// ...` or slash-double-star block. | *** #### DocstringFormat [Section titled “DocstringFormat”](#docstringformat) The format of a docstring extracted from source code. Identifies the docstring convention used, which varies by language (e.g., Python triple-quoted strings, JSDoc, Rustdoc `///` comments). ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-2) Unit variants serialize as a bare string (`"JSDoc"`); the `Other` variant serializes as a single-keyed object (`{"Other": "rst"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ------------------- | -------------------------------------------------------------------------------------------------- | | `PythonTripleQuote` | Python triple-quoted string docstring (`"""..."""`). | | `JsDoc` | JavaScript/TypeScript JSDoc block comment (opens with two stars, closes with star-slash). | | `Rustdoc` | Rust `///` or `//!` doc comment. | | `GoDoc` | Go doc comment (a comment block immediately preceding a declaration). | | `JavaDoc` | Java Javadoc block comment (opens with two stars, closes with star-slash). | | `Other` | A language-specific docstring format not covered by the standard variants. — Fields: `0`: `string` | *** #### ExportKind [Section titled “ExportKind”](#exportkind) The kind of an export statement found in source code. Covers named exports, default exports, and re-exports from other modules. | Value | Description | | ---------- | -------------------------------------------------------------------- | | `Named` | A named export (e.g., `export { foo }`). | | `Default` | A default export (e.g., `export default foo`). | | `ReExport` | A re-export from another module (e.g., `export { foo } from 'bar'`). | *** #### SymbolKind [Section titled “SymbolKind”](#symbolkind) The kind of a symbol definition found in source code. Categorizes symbol definitions such as variables, constants, functions, classes, types, interfaces, enums, and modules. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-3) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | --------------------------------------------------------------------------- | | `Variable` | A variable binding. | | `Constant` | A constant (immutable binding). | | `Function` | A function definition. | | `Class` | A class definition. | | `Type` | A type alias or typedef. | | `Interface` | An interface definition. | | `Enum` | An enum definition. | | `Module` | A module declaration. | | `Other` | A symbol kind not covered by the standard variants. — Fields: `0`: `string` | *** #### DiagnosticSeverity [Section titled “DiagnosticSeverity”](#diagnosticseverity) Severity level of a diagnostic produced during parsing. Used to classify parse errors, warnings, and informational messages found in the syntax tree. | Value | Description | | --------- | --------------------------------------------------------------- | | `Error` | A parse error (e.g., an `ERROR` or `MISSING` node in the tree). | | `Warning` | A warning-level diagnostic. | | `Info` | An informational diagnostic. | *** ### Errors [Section titled “Errors”](#errors) #### Error [Section titled “Error”](#error) Errors that can occur when using the tree-sitter language pack. Covers language lookup failures, parse errors, query errors, and I/O issues. Feature-gated variants are included when `config`, `download`, or related features are enabled. ##### Matching on `Error` [Section titled “Matching on Error”](#matching-on-error) The set of variants is not stable: new failure modes are added in minor releases, and `Io`, `Json`, and `Toml` exist only under certain feature combinations, so the variant set a downstream crate sees depends on which features it enables. Downstream `match`es must therefore carry a `_` arm; `#[non_exhaustive]` makes the compiler enforce that instead of letting a feature change silently break a build. ##### C ABI error codes [Section titled “C ABI error codes”](#c-abi-error-codes) Each variant alef can see carries an explicit `alef(error_code = N)` allocation that becomes a member of the generated `AlefFfiErrorCode` C enum. These numbers are a public ABI contract: **an allocated number is never reused after its variant is removed**, and a variant’s number never changes, because C callers compare against the value, not the name. New variants take the next free number. 0-4 are reserved by alef, so allocation starts at 100. An unannotated variant is emitted as the unknown code rather than as itself, which silently flattens the taxonomy — annotate every new variant. Errors are thrown as plain `Error` objects with descriptive messages. | Variant | Description | | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `LanguageNotFound` | The requested language name (or alias) was not found in the registry. | | `DynamicLoad` | A dynamic shared library could not be loaded at runtime. | | `NullLanguagePointer` | The tree-sitter language function returned a null pointer for the given language name. | | `ParserSetup` | The language could not be applied to the parser (e.g., ABI version mismatch). | | `LockPoisoned` | An internal `RwLock` or `Mutex` was poisoned by a previous panic. | | `Config` | A configuration file or value was invalid or could not be applied. | | `ParseFailed` | The tree-sitter parser returned no tree for the given source input. | | `ParseTimeout` | The parse was cancelled because it exceeded its configured wall-clock budget. Raised only when a budget is configured — see `ProcessConfig.parse_timeout_ms`, which defaults to `null`. | | `QueryError` | A tree-sitter query could not be compiled or executed. | | `InvalidRange` | A byte range was invalid (e.g., end before start, or out of bounds). | | `Download` | A parser download from GitHub releases failed. | | `ChecksumMismatch` | The downloaded file’s SHA-256 digest did not match the manifest’s expected value. | | `CacheLock` | The cross-process download cache lock file could not be acquired or created. | *** # Zig API Reference ## Zig API Reference v1.16.1 [Section titled “Zig API Reference v1.16.1”](#zig-api-reference-v1161) ### Functions [Section titled “Functions”](#functions) #### detect\_language\_from\_extension() [Section titled “detect\_language\_from\_extension()”](#detect_language_from_extension) Detect language name from a file extension (without leading dot). Returns `null` for unrecognized extensions. The match is case-insensitive. **Signature:** ```zig pub fn detect_language_from_extension(ext: []const u8) ?[]u8 ``` **Example:** ```zig const result = detect_language_from_extension("value"); ``` **Parameters:** | Name | Type | Required | Description | | ----- | -------------- | -------- | ----------- | | `ext` | `\[\]const u8` | Yes | The ext | **Returns:** `?[]u8` *** #### detect\_language\_from\_path() [Section titled “detect\_language\_from\_path()”](#detect_language_from_path) Detect language name from a file path. Extracts the file extension and looks it up. Returns `null` if the path has no extension or the extension is not recognized. **Signature:** ```zig pub fn detect_language_from_path(path: []const u8) ?[]u8 ``` **Example:** ```zig const result = detect_language_from_path("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------------- | -------- | ---------------- | | `path` | `\[\]const u8` | Yes | Path to the file | **Returns:** `?[]u8` *** #### detect\_language\_from\_content() [Section titled “detect\_language\_from\_content()”](#detect_language_from_content) Detect language name from file content using the shebang line (`#!`). Inspects only the first line of `content`. If it begins with `#!`, the interpreter name is extracted and mapped to a language name. Handles common patterns: * `#!/usr/bin/env python3` → `"python"` * `#!/bin/bash` → `"bash"` * `#!/usr/bin/env node` → `"javascript"` The `-S` flag accepted by some `env` implementations is skipped automatically. Version suffixes (e.g. `python3.11`, `ruby3.2`) are stripped before matching. A leading UTF-8 BOM (`U+FEFF`) is skipped before the `#!` check, so a BOM-prefixed script is still detected by its shebang. Returns `null` when content does not start with `#!` (after stripping a leading BOM), the shebang is malformed, or the interpreter is not recognised. **Signature:** ```zig pub fn detect_language_from_content(content: []const u8) ?[]u8 ``` **Example:** ```zig const result = detect_language_from_content("value"); ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------------- | -------- | ---------------------- | | `content` | `\[\]const u8` | Yes | The content to process | **Returns:** `?[]u8` *** #### get\_highlights\_query() [Section titled “get\_highlights\_query()”](#get_highlights_query) Get the highlights query for a language, if bundled. Returns the contents of `highlights.scm` as a static string, or `null` if no highlights query is bundled for this language. **Signature:** ```zig pub fn get_highlights_query(language: []const u8) ?[]u8 ``` **Example:** ```zig const result = get_highlights_query("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------------- | -------- | ------------ | | `language` | `\[\]const u8` | Yes | The language | **Returns:** `?[]u8` *** #### get\_injections\_query() [Section titled “get\_injections\_query()”](#get_injections_query) Get the injections query for a language, if bundled. Returns the contents of `injections.scm` as a static string, or `null` if no injections query is bundled for this language. **Signature:** ```zig pub fn get_injections_query(language: []const u8) ?[]u8 ``` **Example:** ```zig const result = get_injections_query("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------------- | -------- | ------------ | | `language` | `\[\]const u8` | Yes | The language | **Returns:** `?[]u8` *** #### get\_locals\_query() [Section titled “get\_locals\_query()”](#get_locals_query) Get the locals query for a language, if bundled. Returns the contents of `locals.scm` as a static string, or `null` if no locals query is bundled for this language. **Signature:** ```zig pub fn get_locals_query(language: []const u8) ?[]u8 ``` **Example:** ```zig const result = get_locals_query("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------------- | -------- | ------------ | | `language` | `\[\]const u8` | Yes | The language | **Returns:** `?[]u8` *** #### get\_tags\_query() [Section titled “get\_tags\_query()”](#get_tags_query) Get the tags query for a language, if bundled. Returns the contents of `tags.scm` as a static string, or `null` if no tags query is bundled for this language. **Signature:** ```zig pub fn get_tags_query(language: []const u8) ?[]u8 ``` **Example:** ```zig const result = get_tags_query("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------------- | -------- | ------------ | | `language` | `\[\]const u8` | Yes | The language | **Returns:** `?[]u8` *** #### get\_indents\_query() [Section titled “get\_indents\_query()”](#get_indents_query) Get the indents query for a language, if bundled. Returns the contents of `indents.scm` (used for auto-indentation) as a static string, or `null` if no indents query is bundled for this language. **Signature:** ```zig pub fn get_indents_query(language: []const u8) ?[]u8 ``` **Example:** ```zig const result = get_indents_query("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------------- | -------- | ------------ | | `language` | `\[\]const u8` | Yes | The language | **Returns:** `?[]u8` *** #### get\_folds\_query() [Section titled “get\_folds\_query()”](#get_folds_query) Get the folds query for a language, if bundled. Returns the contents of `folds.scm` (used for code folding) as a static string, or `null` if no folds query is bundled for this language. **Signature:** ```zig pub fn get_folds_query(language: []const u8) ?[]u8 ``` **Example:** ```zig const result = get_folds_query("value"); ``` **Parameters:** | Name | Type | Required | Description | | ---------- | -------------- | -------- | ------------ | | `language` | `\[\]const u8` | Yes | The language | **Returns:** `?[]u8` *** #### get\_language() [Section titled “get\_language()”](#get_language) Get a tree-sitter `Language` by name using the global registry. Resolves language aliases (e.g., `"shell"` maps to `"bash"`). When the `download` feature is enabled (default), automatically downloads the parser from GitHub releases if not found locally. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.Download` if auto-download fails. **Signature:** ```zig pub fn get_language(name: []const u8) Error!Language ``` **Example:** ```zig const result = try get_language("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------------- | -------- | ----------- | | `name` | `\[\]const u8` | Yes | The name | **Returns:** `Language` **Errors:** Throws `Error`. *** #### get\_parser() [Section titled “get\_parser()”](#get_parser) Get a `Parser` pre-configured for the given language. This is a convenience function that calls `get_language` and configures a new parser in one step. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language cannot be applied to the parser. **Signature:** ```zig pub fn get_parser(name: []const u8) Error!Parser ``` **Example:** ```zig const result = try get_parser("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------------- | -------- | ----------- | | `name` | `\[\]const u8` | Yes | The name | **Returns:** `Parser` **Errors:** Throws `Error`. *** #### detect\_language() [Section titled “detect\_language()”](#detect_language) Detect language name from a file path or extension. This compatibility alias matches the pre-Alef Python binding API. **Signature:** ```zig pub fn detect_language(path: []const u8) ?[]u8 ``` **Example:** ```zig const result = detect_language("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------------- | -------- | ---------------- | | `path` | `\[\]const u8` | Yes | Path to the file | **Returns:** `?[]u8` *** #### available\_languages() [Section titled “available\_languages()”](#available_languages) List all available language names (sorted, deduplicated, includes aliases). Returns names of both statically compiled and dynamically loadable languages, plus any configured aliases. **Signature:** ```zig pub fn available_languages() []u8 ``` **Example:** ```zig const result = available_languages(); ``` **Returns:** `[]u8` *** #### has\_language() [Section titled “has\_language()”](#has_language) Check if a language is available by name or alias. Returns `true` if the language can be loaded (statically compiled, dynamically available, or a known alias for one of these). **Signature:** ```zig pub fn has_language(name: []const u8) bool ``` **Example:** ```zig const result = has_language("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------------- | -------- | ----------- | | `name` | `\[\]const u8` | Yes | The name | **Returns:** `bool` *** #### language\_count() [Section titled “language\_count()”](#language_count) Return the number of available languages. Includes statically compiled languages, dynamically loadable languages, and aliases. **Signature:** ```zig pub fn language_count() u64 ``` **Example:** ```zig const result = language_count(); ``` **Returns:** `u64` *** #### process() [Section titled “process()”](#process) Process source code and extract file intelligence using the global registry. Parses the source with tree-sitter and extracts metrics, structure, imports, exports, comments, docstrings, symbols, diagnostics, and/or chunks based on the flags set in `ProcessConfig`. **Errors:** Returns `Error.InvalidRange` if the config carries a zero-valued limit or the source exceeds `ProcessConfig.max_source_bytes`, `Error.ParseTimeout` if the parse exceeds `ProcessConfig.parse_timeout_ms`, `Error.LanguageNotFound` if the language is unknown, or `Error.ParseFailed` if parsing yields no tree. **Signature:** ```zig pub fn process(source: []const u8, config: []const u8) Error![]u8 ``` **Example:** ```zig const result = try process("value", .{}); ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------------- | -------- | ------------------------- | | `source` | `\[\]const u8` | Yes | The source | | `config` | `\[\]const u8` | Yes | The configuration options | **Returns:** `[]u8` **Errors:** Throws `Error`. *** #### init() [Section titled “init()”](#init) Initialize the language pack with the given configuration. Applies any custom cache directory, then downloads all languages and groups specified in the config. This is the recommended entry point when you want to pre-warm the cache before use. **Errors:** Returns an error if configuration cannot be applied or if downloads fail. **Signature:** ```zig pub fn init(config: []const u8) Error!void ``` **Example:** ```zig try init(.{}); ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------------- | -------- | ------------------------- | | `config` | `\[\]const u8` | Yes | The configuration options | **Returns:** No return value. **Errors:** Throws `Error`. *** #### configure() [Section titled “configure()”](#configure) Apply download configuration without downloading anything. Use this to set a custom cache directory before the first call to `get_language` or any download function. Changing the cache dir after languages have been registered has no effect on already-loaded languages. `PackConfig.cache_dir` is a BASE directory, not the final libs path: this crate appends `tree-sitter-language-pack/v{version}/libs` to it, the same suffix applied to the platform default cache directory. In the example below, files actually land under `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`, never directly in `/tmp/my-parsers/`. Call `cache_dir` to read back the resolved, fully-suffixed path. **Errors:** Returns an error if the lock cannot be acquired. **Signature:** ```zig pub fn configure(config: []const u8) Error!void ``` **Example:** ```zig try configure(.{}); ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------------- | -------- | ------------------------- | | `config` | `\[\]const u8` | Yes | The configuration options | **Returns:** No return value. **Errors:** Throws `Error`. *** #### download() [Section titled “download()”](#download) Download specific languages to the local cache. Returns the number of distinct languages available after the call. Already compiled or cached languages are included in the count. Aliases are resolved before counting, so `["shell", "bash"]` names one language and returns 1. **Errors:** Returns an error if any language is not available in the manifest or if the download fails. **Signature:** ```zig pub fn download(names: []const u8) Error!u64 ``` **Example:** ```zig const result = try download(&[_]u8{}); ``` **Parameters:** | Name | Type | Required | Description | | ------- | -------------- | -------- | ----------- | | `names` | `\[\]const u8` | Yes | The names | **Returns:** `u64` **Errors:** Throws `Error`. *** #### prefetch() [Section titled “prefetch()”](#prefetch) Prefetch grammars: download any not already loadable from disk, then load every requested language into the process registry so a subsequent hot loop only parses. Unlike `download()`, this does not trust in-memory availability — it downloads whenever a grammar is not actually loadable from disk (fixing the case where a known-but-not-downloaded grammar is reported present), then resolves and caches every requested language. Call it once, up front, before a parallel workload. **Errors:** Returns `Error.Download` if a required grammar cannot be fetched, or `Error.LanguageNotFound` if a requested name is unknown. **Signature:** ```zig pub fn prefetch(languages: []const u8) Error!void ``` **Example:** ```zig try prefetch(&[_]u8{}); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | -------------- | -------- | ------------- | | `languages` | `\[\]const u8` | Yes | The languages | **Returns:** No return value. **Errors:** Throws `Error`. *** #### download\_all() [Section titled “download\_all()”](#download_all) Download all available languages from the remote manifest. Downloads the platform bundle and extracts every library it contains. Languages that appear in the manifest but are absent from the bundle (e.g. grammars that failed to compile at release time) are silently skipped — they are not treated as an error. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns an error if the manifest cannot be fetched or the bundle download fails. **Signature:** ```zig pub fn download_all() Error!u64 ``` **Example:** ```zig const result = try download_all(); ``` **Returns:** `u64` **Errors:** Throws `Error`. *** #### download\_group() [Section titled “download\_group()”](#download_group) Download every language in a named group. Groups are defined by the remote manifest, not by this library, and let you ensure a curated set of related grammars in one call instead of listing each name to `download()`. Already-cached languages are skipped. Call `manifest_groups` to discover the group names the manifest actually defines. The published manifest currently defines a single group, `"all"`; earlier revisions of this documentation advertised `"web"`, `"data"`, and `"systems"`, which the manifest has never contained, so every call following that example failed. Do not hardcode a group name without checking. Returns the total number of languages now available (statically compiled plus downloaded and cached). **Errors:** Returns `Error.Download` if the manifest cannot be fetched, if the group is unknown — the message lists the groups the manifest defines — or if any constituent language fails to download. **Signature:** ```zig pub fn download_group(name: []const u8) Error!u64 ``` **Example:** ```zig const result = try download_group("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------------- | -------- | ----------- | | `name` | `\[\]const u8` | Yes | The name | **Returns:** `u64` **Errors:** Throws `Error`. *** #### manifest\_languages() [Section titled “manifest\_languages()”](#manifest_languages) Return all language names available in the remote manifest (371). Fetches (and caches) the remote manifest to discover the full list of downloadable languages. Use `downloaded_languages` to list what is already cached locally. **Errors:** Returns an error if the manifest cannot be fetched. **Signature:** ```zig pub fn manifest_languages() Error![]u8 ``` **Example:** ```zig const result = try manifest_languages(); ``` **Returns:** `[]u8` **Errors:** Throws `Error`. *** #### manifest\_groups() [Section titled “manifest\_groups()”](#manifest_groups) Return the names of every language group the remote manifest defines, sorted. Group names are manifest data, not a compile-time constant of this library, so this is the only reliable way to learn what `download_group` and `PackConfig.groups` accept. The published manifest currently defines just `"all"`. **Errors:** Returns `Error.Download` if the manifest cannot be fetched. **Signature:** ```zig pub fn manifest_groups() Error![]u8 ``` **Example:** ```zig const result = try manifest_groups(); ``` **Returns:** `[]u8` **Errors:** Throws `Error`. *** #### downloaded\_languages() [Section titled “downloaded\_languages()”](#downloaded_languages) Return languages that are already downloaded and cached locally. Does not perform any network requests. Returns an empty list if the cache directory does not exist or cannot be read. **Signature:** ```zig pub fn downloaded_languages() []u8 ``` **Example:** ```zig const result = downloaded_languages(); ``` **Returns:** `[]u8` *** #### clean\_cache() [Section titled “clean\_cache()”](#clean_cache) Delete all cached parser shared libraries. Resets the cache registration so the next call to `get_language` or a download function will re-register the (now empty) cache directory. **Errors:** Returns an error if the cache directory cannot be removed. **Signature:** ```zig pub fn clean_cache() Error!void ``` **Example:** ```zig try clean_cache(); ``` **Returns:** No return value. **Errors:** Throws `Error`. *** #### cache\_dir() [Section titled “cache\_dir()”](#cache_dir) Return the effective cache directory path. This is `{base}/tree-sitter-language-pack/v{version}/libs/`, where `{base}` is either the custom BASE directory set via `configure` / `init` (`PackConfig.cache_dir`) or the platform default cache directory — both are suffixed identically, so a custom `cache_dir` is never used as the final libs path. The default resolves to `~/.cache/tree-sitter-language-pack/v{version}/libs/` on a typical Unix system. **Errors:** Returns an error if no cache directory can be resolved: `version` is somehow invalid, or (with no custom `cache_dir` configured) the platform reports none and `TREE_SITTER_LANGUAGE_PACK_CACHE_DIR` is unset. This crate no longer falls back to the temporary directory for the latter case — see #101 H2. **Signature:** ```zig pub fn cache_dir() Error![]u8 ``` **Example:** ```zig const result = try cache_dir(); ``` **Returns:** `[]u8` **Errors:** Throws `Error`. *** ### Types [Section titled “Types”](#types) #### ByteRange [Section titled “ByteRange”](#byterange) A byte range — start (inclusive) to end (exclusive). | Field | Type | Default | Description | | ------- | ----- | ------- | ---------------------------- | | `start` | `u64` | — | Inclusive start byte offset. | | `end` | `u64` | — | Exclusive end byte offset. | *** #### ChunkContext [Section titled “ChunkContext”](#chunkcontext) Metadata for a single chunk of source code. | Field | Type | Default | Description | | ----------------- | ------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `\[\]const u8` | — | Language name used to parse this chunk. | | `chunk_index` | `u64` | — | Zero-indexed position of this chunk within the file’s chunk list. | | `total_chunks` | `u64` | — | Total number of chunks the file was split into. | | `node_types` | `\[\]const \[\]const u8` | `[]` | Tree-sitter node kinds that appear at the top level of this chunk. | | `context_path` | `\[\]const \[\]const u8` | `[]` | Hierarchical path of enclosing structural items (e.g., `["MyClass", "my_method"]`). | | `symbols_defined` | `\[\]const \[\]const u8` | `[]` | Names of symbols defined within this chunk. | | `comments` | `\[\]const CommentInfo` | `[]` | Comments contained within this chunk. | | `docstrings` | `\[\]const DocstringInfo` | `[]` | Docstrings contained within this chunk. Populated only for Python — the same language for which `ProcessResult.docstrings` is populated, and by the same classifier. Always empty for every other language. | | `has_error_nodes` | `bool` | — | Whether this chunk contains any tree-sitter error nodes. | *** #### CodeChunk [Section titled “CodeChunk”](#codechunk) A chunk of source code with rich metadata. | Field | Type | Default | Description | | ------------ | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `content` | `\[\]const u8` | — | The raw source text of this chunk. | | `start_byte` | `u64` | — | Inclusive start byte offset of this chunk in the original source. | | `end_byte` | `u64` | — | Exclusive end byte offset of this chunk in the original source. | | `start_line` | `u64` | — | Zero-indexed start line of this chunk. | | `end_line` | `u64` | — | Zero-indexed row of the last byte actually included in this chunk (inclusive — the same row a `Span.end_line` would report for a node ending on that byte). Computed the same way regardless of whether the source has a trailing newline: it is always the row of `end_byte - 1`, never a phantom row past the file’s real content. | | `metadata` | `ChunkContext` | — | Contextual metadata about this chunk. | *** #### CommentInfo [Section titled “CommentInfo”](#commentinfo) A comment extracted from source code. | Field | Type | Default | Description | | ----------------- | --------------- | ------------------ | ----------------------------------------------------------------- | | `text` | `\[\]const u8` | — | The raw text content of the comment. | | `kind` | `CommentKind` | `CommentKind.line` | The kind of comment (line, block, or doc). | | `span` | `Span` | — | Source span covering the comment. | | `associated_node` | `\[\]const u8?` | `null` | Name of the syntax node this comment is directly associated with. | *** #### DataAttribute [Section titled “DataAttribute”](#dataattribute) An XML-style attribute attached to an `Element` node. Populated only for `DataNodeKind.Element`; always empty for `KeyValue` and `Sequence` nodes. | Field | Type | Default | Description | | ------- | -------------- | ------- | --------------------------------------------------------------- | | `name` | `\[\]const u8` | — | Attribute name (e.g. `"class"`, `"href"`). | | `value` | `\[\]const u8` | — | Attribute value as a raw string (quotes stripped). | | `span` | `Span` | — | Source span covering the entire `name="value"` attribute token. | *** #### DataNode [Section titled “DataNode”](#datanode) A node in the hierarchical data tree produced by data-format extraction. When `ProcessConfig.data_extraction` is `true`, `ProcessResult.data` is populated with a root `DataNode` whose `children` mirror the structure of the parsed file. The `kind` field determines which other fields are meaningful: | `kind` | `key` | `value` | `attributes` | `children` | | ---------- | ------------------------- | ------------ | ------------ | -------------- | | `KeyValue` | key / mapping key / index | leaf value | empty | nested map | | `Element` | XML tag name | text content | XML attrs | child elements | | `Sequence` | positional index (`"0"`) | leaf value | empty | sub-items | | Field | Type | Default | Description | | ------------ | ------------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------- | | `kind` | `DataNodeKind` | `DataNodeKind.key_value` | Whether this node is a key/value pair, XML element, or sequence item. | | `key` | `\[\]const u8?` | `null` | Key, attribute name, tag name, or positional index (`"0"`, `"1"`, …). `null` at the document root. | | `value` | `\[\]const u8?` | `null` | Leaf scalar value, if any. `null` for containers (objects, arrays, XML elements with child elements). | | `attributes` | `\[\]const DataAttribute` | `[]` | Attributes on element-shape nodes (XML `STag` attributes). Empty for all other kinds. | | `children` | `\[\]const DataNode` | `[]` | Children for nested containers and XML element bodies. | | `span` | `Span` | — | Source span covering this node in the original source file. | *** #### Diagnostic [Section titled “Diagnostic”](#diagnostic) A diagnostic (syntax error, missing node, etc.) from parsing. | Field | Type | Default | Description | | ---------- | -------------------- | -------------------------- | ---------------------------------------------- | | `message` | `\[\]const u8` | — | Human-readable description of the diagnostic. | | `severity` | `DiagnosticSeverity` | `DiagnosticSeverity.error` | Severity of the diagnostic. | | `span` | `Span` | — | Source span where the diagnostic was detected. | *** #### DocSection [Section titled “DocSection”](#docsection) A section within a docstring (e.g., Args, Returns, Raises). | Field | Type | Default | Description | | ------------- | --------------- | ------- | ------------------------------------------------------- | | `kind` | `\[\]const u8` | — | Section kind (e.g., `"args"`, `"returns"`, `"raises"`). | | `name` | `\[\]const u8?` | `null` | Parameter or return value name, if applicable. | | `description` | `\[\]const u8` | — | Description text for this section. | *** #### DocstringInfo [Section titled “DocstringInfo”](#docstringinfo) A docstring extracted from source code. | Field | Type | Default | Description | | ----------------- | ---------------------- | ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | `\[\]const u8` | — | The raw text of the docstring. | | `format` | `DocstringFormat` | `DocstringFormat.python_triple_quote` | The docstring format (Python, JSDoc, Rustdoc, etc.). | | `span` | `Span` | — | Source span covering the docstring. | | `associated_item` | `\[\]const u8?` | `null` | Name of the item this docstring documents. | | `parsed_sections` | `\[\]const DocSection` | `[]` | Parsed sections of the docstring (Args, Returns, Raises, etc.). **Reserved: not yet populated.** Always empty, for every `DocstringFormat`. Parsing a docstring body into sections requires implementing each convention’s own layout (Google/NumPy/reST style for Python, `@param`/`@returns` for JSDoc/Javadoc, and so on), which no extractor here does yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | *** #### DownloadManager [Section titled “DownloadManager”](#downloadmanager) Manages downloading and caching of pre-built parser shared libraries. ##### Methods [Section titled “Methods”](#methods) ###### new() [Section titled “new()”](#new) Create a new download manager for the given version. **Errors:** Returns `Error.Download` if `version` is empty, contains a path separator or `..`, or contains a character outside `[A-Za-z0-9.+-]` — see `validate_version` — or if no cache directory can be resolved (see `Self.default_cache_dir`). **Signature:** ```zig pub fn new_download_manager(version: []const u8) Error!DownloadManager ``` **Example:** ```zig const result = try new_download_manager("value"); ``` **Parameters:** | Name | Type | Required | Description | | --------- | -------------- | -------- | ----------- | | `version` | `\[\]const u8` | Yes | The version | **Returns:** `DownloadManager` **Errors:** Throws `Error`. ###### installed\_languages() [Section titled “installed\_languages()”](#installed_languages) List languages that are already downloaded and cached. Derived from the on-disk cache filenames, one canonical name per file, plus every alias that resolves to it (via `aliases_for`) — so this list agrees with the user-facing `LanguageRegistry.available_languages` about which names are “available”; both report `"shell"` once `bash` is cached, for example. A previous version reported canonical names only, which could never agree with `available_languages()`. See #107. Returns an empty list if the cache directory does not exist. If it exists but cannot be read (e.g. a permission error), also returns an empty list — changing this to a `Result` would be a breaking change across every language binding — but logs a `tracing.warn!` so the failure is not silently indistinguishable from “nothing installed”. **Signature:** ```zig pub fn installed_languages(self: *const DownloadManager) []u8 ``` **Example:** ```zig const result = instance.installed_languages(); ``` **Returns:** `[]u8` ###### download\_all\_best\_effort() [Section titled “download\_all\_best\_effort()”](#download_all_best_effort) Download the platform bundle and extract every library file it contains. Unlike `Self.ensure_languages`, this does not check the manifest language list against archive contents — it simply extracts all `.so`/`.dylib`/`.dll` files from the bundle. Languages in the manifest that are missing from the archive are silently ignored rather than returning an error. Returns the number of library files extracted (including those already cached). **Signature:** ```zig pub fn download_all_best_effort(self: *const DownloadManager) Error!u64 ``` **Example:** ```zig const result = try instance.download_all_best_effort(); ``` **Returns:** `u64` **Errors:** Throws `Error`. ###### clean\_cache() [Section titled “clean\_cache()”](#clean_cache-1) Remove all cached parser libraries. Acquires the cross-process lock so `clean_cache` cannot race a concurrent downloader (avoids Windows sharing-violation errors against an in-flight bundle write). The `.download.lock` file itself is **not** removed — it is permanent infrastructure; deleting it could allow a concurrent process that already opened the file to continue holding a stale lock handle while a new process opens a fresh inode, breaking the mutual-exclusion guarantee. **Signature:** ```zig pub fn clean_cache(self: *const DownloadManager) Error!void ``` **Example:** ```zig try instance.clean_cache(); ``` **Returns:** No return value. **Errors:** Throws `Error`. *** #### ExportInfo [Section titled “ExportInfo”](#exportinfo) An export statement extracted from source code. | Field | Type | Default | Description | | ------ | -------------- | ------------------ | -------------------------------------------------- | | `name` | `\[\]const u8` | — | The exported name. | | `kind` | `ExportKind` | `ExportKind.named` | The kind of export (named, default, or re-export). | | `span` | `Span` | — | Source span covering the export statement. | *** #### FileMetrics [Section titled “FileMetrics”](#filemetrics) Aggregate metrics for a source file. | Field | Type | Default | Description | | --------------- | ----- | ------- | -------------------------------------------------------------- | | `total_lines` | `u64` | — | Total number of lines (including blank and comment lines). | | `code_lines` | `u64` | — | Number of lines containing non-blank, non-comment source code. | | `comment_lines` | `u64` | — | Number of lines that are entirely comments. | | `blank_lines` | `u64` | — | Number of blank (whitespace-only) lines. | | `total_bytes` | `u64` | — | Total byte length of the source file. | | `node_count` | `u64` | — | Total number of nodes in the syntax tree. | | `error_count` | `u64` | — | Number of error nodes in the syntax tree (parse errors). | | `max_depth` | `u64` | — | Maximum nesting depth reached in the syntax tree. | *** #### ImportInfo [Section titled “ImportInfo”](#importinfo) An import statement extracted from source code. | Field | Type | Default | Description | | ------------- | ------------------------ | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `source` | `\[\]const u8` | — | The module or path being imported from. | | `items` | `\[\]const \[\]const u8` | `[]` | Specific names imported from the source module. For `import a, b` / `from m import a, b`, every entry’s base name (never the alias). For a JavaScript/TypeScript named-imports clause (`import { a, b as c } from 'm'`), every specifier’s original name. Populated for Python and JavaScript/TypeScript only. Always empty for every other language this library recognises import statements for — Rust, Go, Java, Kotlin, and Elixir (`import`/`alias`/`require`/`use`) — and for a JS/TS namespace import (`import * as ns`) or default import (`import x from 'm'`), neither of which names individual items. | | `alias` | `\[\]const u8?` | `null` | Alias assigned to the import (e.g., `import numpy as np`). Populated for Python’s single-name form (`import numpy as np`, `from m import a as b`) and JavaScript/TypeScript’s namespace form (`import * as ns from 'm'`) or a named-imports clause naming exactly one specifier (`import { a as b } from 'm'`). `null` for Rust, Go, Java, Kotlin, and Elixir (which has its own `as:` alias option on `alias` directives, not yet extracted here) — and for a Python statement that aliases several names at once (`import os, sys as s`), where there is no single alias to report for the statement as a whole, so only `items` is populated for it. | | `is_wildcard` | `bool` | — | Whether this is a wildcard import (e.g., `import *` or `use foo.*`). Detected from the syntax tree — a dedicated wildcard node (`wildcard_import` in Python, `use_wildcard` in Rust) or a bare `*` token outside of string-literal content — not by searching the import’s source text for a `*` character, so a glob in an import path string (`import a from './glob*.js'`) is not mistaken for one. | | `span` | `Span` | — | Source span covering the import statement. | *** #### Language [Section titled “Language”](#language) *** #### LanguageRegistry [Section titled “LanguageRegistry”](#languageregistry) Thread-safe registry of tree-sitter language parsers. Manages both statically compiled and dynamically loaded language grammars. Use `LanguageRegistry.new()` for the default registry, or access the global instance via the module-level convenience functions (`get_language`, `available_languages`, etc.). ##### Methods [Section titled “Methods”](#methods-1) ###### new() [Section titled “new()”](#new-1) Create a new registry populated with all statically compiled languages. When the `dynamic-loading` feature is enabled, the registry also knows about dynamically loadable grammars and will load them on demand. **Signature:** ```zig pub fn new_language_registry() LanguageRegistry ``` **Example:** ```zig const result = new_language_registry(); ``` **Returns:** `LanguageRegistry` ###### get\_language() [Section titled “get\_language()”](#get_language-1) Get a tree-sitter `Language` by name. Resolves aliases (e.g., `"shell"` -> `"bash"`, `"makefile"` -> `"make"`), then looks up the language in the static table. When the `dynamic-loading` feature is enabled, falls back to loading a shared library on demand. **Errors:** Returns `Error.LanguageNotFound` if the name (after alias resolution) does not match any known grammar. **Signature:** ```zig pub fn get_language(self: *const LanguageRegistry, name: []const u8) Error!Language ``` **Example:** ```zig const result = try instance.get_language("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------------- | -------- | ----------- | | `name` | `\[\]const u8` | Yes | The name | **Returns:** `Language` **Errors:** Throws `Error`. ###### available\_languages() [Section titled “available\_languages()”](#available_languages-1) List all available language names, sorted and deduplicated. Includes statically compiled languages, dynamically loadable languages (if the `dynamic-loading` feature is enabled), and all configured aliases. **Signature:** ```zig pub fn available_languages(self: *const LanguageRegistry) []u8 ``` **Example:** ```zig const result = instance.available_languages(); ``` **Returns:** `[]u8` ###### has\_parser() [Section titled “has\_parser()”](#has_parser) Check whether this language can be parsed right now, without downloading. Resolves aliases, then answers from exactly the lookup `get_language` performs: the statically compiled table, the already-loaded dynamic grammars, and the parser shared libraries present in the primary and extra (download-cache) library directories. It never performs network I/O. A previous implementation consulted only the statically compiled table. That table is empty in every build that does not set `TSLP_LANGUAGES`, so the function answered `false` for languages this registry parses perfectly well. Contrast `has_language`, which is also `true` for a grammar that is merely *known to the manifest* and would have to be downloaded first. The pair distinguishes “we can parse it offline, now” from “we recognise the name”. The first `true` answer for a dynamic grammar loads its shared library: loading is the only way to know the grammar is usable, since a truncated or wrong-architecture library exists on disk but cannot parse. Loads are cached process-wide, so repeat calls are cheap. **Signature:** ```zig pub fn has_parser(self: *const LanguageRegistry, name: []const u8) bool ``` **Example:** ```zig const result = instance.has_parser("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------------- | -------- | ----------- | | `name` | `\[\]const u8` | Yes | The name | **Returns:** `bool` ###### has\_language() [Section titled “has\_language()”](#has_language-1) Check whether a language is available by name or alias. Returns `true` if the language can be loaded, either from the static table or from a dynamic library on disk. Every branch is one more way to answer `true`, so they are ordered cheapest-first and the filesystem is only consulted once every in-memory source has said no. Probing the loaded-grammar map and the manifest ahead of the `stat` calls is what keeps this off the syscall path for the languages a process actually uses. **Signature:** ```zig pub fn has_language(self: *const LanguageRegistry, name: []const u8) bool ``` **Example:** ```zig const result = instance.has_language("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------------- | -------- | ----------- | | `name` | `\[\]const u8` | Yes | The name | **Returns:** `bool` ###### language\_count() [Section titled “language\_count()”](#language_count-1) Return the total number of available languages (including aliases). Counts the same set `available_languages` lists, without materialising or sorting it. **Signature:** ```zig pub fn language_count(self: *const LanguageRegistry) u64 ``` **Example:** ```zig const result = instance.language_count(); ``` **Returns:** `u64` ###### process() [Section titled “process()”](#process-1) Parse source code and extract file intelligence based on config in a single pass. **Errors:** Returns `Error.InvalidRange` if the config is invalid (see `ProcessConfig.validate`) or if the source exceeds the configured `max_source_bytes`; `Error.LanguageNotFound` if the language is unknown; or `Error.ParseFailed` if parsing produces no tree. **Signature:** ```zig pub fn process(self: *const LanguageRegistry, source: []const u8, config: []const u8) Error![]u8 ``` **Example:** ```zig const result = try instance.process("value", .{}); ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------------- | -------- | ------------------------- | | `source` | `\[\]const u8` | Yes | The source | | `config` | `\[\]const u8` | Yes | The configuration options | **Returns:** `[]u8` **Errors:** Throws `Error`. *** #### Node [Section titled “Node”](#node) A single syntax node within a `Tree`. Nodes hold a strong reference to their parent tree so they remain valid regardless of how the tree is moved or stored at the FFI boundary. ##### Methods [Section titled “Methods”](#methods-2) ###### kind() [Section titled “kind()”](#kind) Return the node’s kind name (e.g. `"function_definition"`). **Signature:** ```zig pub fn kind(self: *const Node) []u8 ``` **Example:** ```zig const result = instance.kind(); ``` **Returns:** `[]u8` ###### kind\_id() [Section titled “kind\_id()”](#kind_id) Return the node’s numeric kind ID. Tree-sitter assigns a stable `u16` ID to every node kind in a grammar (e.g. `"function_definition" → 42`). Comparing `kind_id()` is cheaper than comparing the string `kind()` in tight AST loops. **Signature:** ```zig pub fn kind_id(self: *const Node) u16 ``` **Example:** ```zig const result = instance.kind_id(); ``` **Returns:** `u16` ###### start\_byte() [Section titled “start\_byte()”](#start_byte) Return the inclusive start byte offset of this node. **Signature:** ```zig pub fn start_byte(self: *const Node) u64 ``` **Example:** ```zig const result = instance.start_byte(); ``` **Returns:** `u64` ###### end\_byte() [Section titled “end\_byte()”](#end_byte) Return the exclusive end byte offset of this node. **Signature:** ```zig pub fn end_byte(self: *const Node) u64 ``` **Example:** ```zig const result = instance.end_byte(); ``` **Returns:** `u64` ###### byte\_range() [Section titled “byte\_range()”](#byte_range) Return the node’s byte range as a `ByteRange`. Callers should slice their own source bytes — this is a zero-copy text accessor. **Signature:** ```zig pub fn byte_range(self: *const Node) []u8 ``` **Example:** ```zig const result = instance.byte_range(); ``` **Returns:** `[]u8` ###### start\_position() [Section titled “start\_position()”](#start_position) Return the start `Point` (row, column). **Signature:** ```zig pub fn start_position(self: *const Node) []u8 ``` **Example:** ```zig const result = instance.start_position(); ``` **Returns:** `[]u8` ###### end\_position() [Section titled “end\_position()”](#end_position) Return the end `Point` (row, column). **Signature:** ```zig pub fn end_position(self: *const Node) []u8 ``` **Example:** ```zig const result = instance.end_position(); ``` **Returns:** `[]u8` ###### is\_named() [Section titled “is\_named()”](#is_named) True when this node is named (not punctuation/whitespace). **Signature:** ```zig pub fn is_named(self: *const Node) bool ``` **Example:** ```zig const result = instance.is_named(); ``` **Returns:** `bool` ###### is\_error() [Section titled “is\_error()”](#is_error) True when this is an error node. **Signature:** ```zig pub fn is_error(self: *const Node) bool ``` **Example:** ```zig const result = instance.is_error(); ``` **Returns:** `bool` ###### is\_missing() [Section titled “is\_missing()”](#is_missing) True when this is a missing-token node. **Signature:** ```zig pub fn is_missing(self: *const Node) bool ``` **Example:** ```zig const result = instance.is_missing(); ``` **Returns:** `bool` ###### is\_extra() [Section titled “is\_extra()”](#is_extra) True when this is an “extra” node (e.g. a comment). **Signature:** ```zig pub fn is_extra(self: *const Node) bool ``` **Example:** ```zig const result = instance.is_extra(); ``` **Returns:** `bool` ###### has\_error() [Section titled “has\_error()”](#has_error) True when this node or any descendant is an error. **Signature:** ```zig pub fn has_error(self: *const Node) bool ``` **Example:** ```zig const result = instance.has_error(); ``` **Returns:** `bool` ###### parent() [Section titled “parent()”](#parent) Return this node’s parent, if any. **Signature:** ```zig pub fn parent(self: *const Node) ?Node ``` **Example:** ```zig const result = instance.parent(); ``` **Returns:** `?Node` ###### child() [Section titled “child()”](#child) Return the i-th child of this node, if any. **Signature:** ```zig pub fn child(self: *const Node, index: u32) ?Node ``` **Example:** ```zig const result = instance.child(42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | ----- | -------- | ----------- | | `index` | `u32` | Yes | The index | **Returns:** `?Node` ###### child\_count() [Section titled “child\_count()”](#child_count) Total number of children (including unnamed). **Signature:** ```zig pub fn child_count(self: *const Node) u64 ``` **Example:** ```zig const result = instance.child_count(); ``` **Returns:** `u64` ###### named\_child() [Section titled “named\_child()”](#named_child) Return the i-th named child of this node, if any. **Signature:** ```zig pub fn named_child(self: *const Node, index: u32) ?Node ``` **Example:** ```zig const result = instance.named_child(42); ``` **Parameters:** | Name | Type | Required | Description | | ------- | ----- | -------- | ----------- | | `index` | `u32` | Yes | The index | **Returns:** `?Node` ###### named\_child\_count() [Section titled “named\_child\_count()”](#named_child_count) Number of named children of this node. **Signature:** ```zig pub fn named_child_count(self: *const Node) u64 ``` **Example:** ```zig const result = instance.named_child_count(); ``` **Returns:** `u64` ###### child\_by\_field\_name() [Section titled “child\_by\_field\_name()”](#child_by_field_name) Look up a child by its grammar-defined field name. **Signature:** ```zig pub fn child_by_field_name(self: *const Node, name: []const u8) ?Node ``` **Example:** ```zig const result = instance.child_by_field_name("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------------- | -------- | ----------- | | `name` | `\[\]const u8` | Yes | The name | **Returns:** `?Node` ###### to\_sexp() [Section titled “to\_sexp()”](#to_sexp) Return the S-expression form of this node’s subtree. **Signature:** ```zig pub fn to_sexp(self: *const Node) []u8 ``` **Example:** ```zig const result = instance.to_sexp(); ``` **Returns:** `[]u8` ###### walk() [Section titled “walk()”](#walk) Return a `TreeCursor` positioned at this node. **Signature:** ```zig pub fn walk(self: *const Node) TreeCursor ``` **Example:** ```zig const result = instance.walk(); ``` **Returns:** `TreeCursor` *** #### PackConfig [Section titled “PackConfig”](#packconfig) Configuration for the tree-sitter language pack. Controls cache directory and which languages to pre-download. Can be loaded from a TOML file, constructed programmatically, or passed as a dict/object from language bindings. | Field | Type | Default | Description | | ----------- | ------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cache_dir` | `\[\]const u8?` | `null` | Override the BASE directory the parser cache lives under. This is a base, not the final library path: the crate appends `tree-sitter-language-pack/v{version}/libs` to it, exactly as it does to the platform default. So `cache_dir = "/tmp/my-parsers"` resolves to `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`. The suffix is not cosmetic. It keeps the whole cache tree — manifest, bundles and lock file included — inside a directory this library owns and versions. Earlier releases used this path verbatim, which put those files in the configured directory’s PARENT and let a cache built by one crate version be reused by another. Default base: the platform cache dir, e.g. `~/.cache` on Linux. | | `languages` | `\[\]const \[\]const u8?` | `[]` | Languages to pre-download on init. Each entry is a language name (e.g. `"python"`, `"rust"`). | | `groups` | `\[\]const \[\]const u8?` | `[]` | Language groups to pre-download. Group names come from the remote manifest, so the valid set is not fixed by this library; the published manifest currently defines only `"all"`. Call `manifest_groups` to enumerate them. An unknown name makes `init` fail. | *** #### Parser [Section titled “Parser”](#parser) A tree-sitter parser configured for one language at a time. ##### Methods [Section titled “Methods”](#methods-3) ###### new() [Section titled “new()”](#new-2) Construct a new parser with no language set and no parse limits. Call `Parser.set_language` before parsing. Limits are opt-in via `set_max_source_bytes` and `set_parse_timeout_ms`; both default to unbounded so that existing callers are unaffected. **Signature:** ```zig pub fn new_parser() Parser ``` **Example:** ```zig const result = new_parser(); ``` **Returns:** `Parser` ###### set\_max\_source\_bytes() [Section titled “set\_max\_source\_bytes()”](#set_max_source_bytes) Refuse to parse sources longer than `max_bytes`. `null` (the default) means no limit. Over-limit input makes `parse` and `parse_bytes` return `null` after emitting a `WARN`; input is never silently truncated. See `RECOMMENDED_MAX_SOURCE_BYTES`. **Signature:** ```zig pub fn set_max_source_bytes(self: *const Parser, max_bytes: ?u64) void ``` **Example:** ```zig instance.set_max_source_bytes(42); ``` **Parameters:** | Name | Type | Required | Description | | ----------- | ------ | -------- | ------------- | | `max_bytes` | `?u64` | No | The max bytes | **Returns:** No return value. ###### set\_parse\_timeout\_ms() [Section titled “set\_parse\_timeout\_ms()”](#set_parse_timeout_ms) Cancel a parse that exceeds `timeout_ms` milliseconds of wall clock. `null` (the default) means no budget. Cancellation runs through tree-sitter’s parse progress callback, so it is granular to that callback’s interval rather than exact. See `RECOMMENDED_PARSE_TIMEOUT_MS`. **Signature:** ```zig pub fn set_parse_timeout_ms(self: *const Parser, timeout_ms: ?u64) void ``` **Example:** ```zig instance.set_parse_timeout_ms(42); ``` **Parameters:** | Name | Type | Required | Description | | ------------ | ------ | -------- | -------------- | | `timeout_ms` | `?u64` | No | The timeout ms | **Returns:** No return value. ###### set\_language() [Section titled “set\_language()”](#set_language) Configure the parser to use the language identified by name (e.g. `"python"`). Resolves the language through the global registry — auto-downloading if necessary, when the `download` feature is enabled. **Errors:** Returns `Error.LanguageNotFound` if the language is not recognized, or `Error.ParserSetup` if the language ABI is incompatible. **Signature:** ```zig pub fn set_language(self: *const Parser, name: []const u8) Error!void ``` **Example:** ```zig try instance.set_language("value"); ``` **Parameters:** | Name | Type | Required | Description | | ------ | -------------- | -------- | ----------- | | `name` | `\[\]const u8` | Yes | The name | **Returns:** No return value. **Errors:** Throws `Error`. ###### parse() [Section titled “parse()”](#parse) Parse a UTF-8 source string. Returns `null` if no language is set, if the parse was cancelled by the configured timeout, or if the source exceeds the configured size limit. Each non-parse outcome is logged, so an empty result is never silent. ###### Concurrency [Section titled “Concurrency”](#concurrency) Parsing runs fully in parallel across threads for almost every language — no lock is taken. The exception is the small set of grammars whose external scanner keeps mutable process-global state (currently just `properties`): parses of that language are serialized against each other through an internal per-language lock, so that concurrent threads can’t corrupt shared scanner state. Every other language is unaffected by that lock and never waits on it. **Signature:** ```zig pub fn parse(self: *const Parser, source: []const u8) ?Tree ``` **Example:** ```zig const result = instance.parse("value"); ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------------- | -------- | ----------- | | `source` | `\[\]const u8` | Yes | The source | **Returns:** `?Tree` ###### parse\_bytes() [Section titled “parse\_bytes()”](#parse_bytes) Parse a raw byte slice. Same outcomes as `parse`, including the concurrency behaviour documented there. **Signature:** ```zig pub fn parse_bytes(self: *const Parser, source: []const u8) ?Tree ``` **Example:** ```zig const result = instance.parse_bytes("data"); ``` **Parameters:** | Name | Type | Required | Description | | -------- | -------------- | -------- | ----------- | | `source` | `\[\]const u8` | Yes | The source | **Returns:** `?Tree` ###### reset() [Section titled “reset()”](#reset) Reset internal state. The next call to `parse` will not be incremental. **Signature:** ```zig pub fn reset(self: *const Parser) void ``` **Example:** ```zig instance.reset(); ``` **Returns:** No return value. *** #### Point [Section titled “Point”](#point) A source position — row + column, zero-indexed. | Field | Type | Default | Description | | -------- | ----- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `row` | `u64` | — | Zero-indexed row number. | | `column` | `u64` | — | Zero-indexed column, counted in **bytes** from the start of the row. This is `tree_sitter.Point.column` verbatim, and tree-sitter defines it as a byte offset — not characters, and not UTF-16 code units. Measured on a row of the form `x = ''` where `` is a single 4-byte character (an emoji), the string node reports columns `4..10`, identical to its byte range; the character columns would be `4..7` and the UTF-16 columns `4..8`. Anything that builds LSP positions (UTF-16) or editor caret columns (characters) from this field is silently wrong on every row containing a non-ASCII byte, and must re-measure the row against the source text instead. Earlier releases documented this field as UTF-16 code units; that was never what the value contained. | *** #### ProcessConfig [Section titled “ProcessConfig”](#processconfig) Configuration for the `process()` function. Controls which analysis features are enabled and whether chunking is performed. | Field | Type | Default | Description | | ------------------ | -------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `\[\]const u8` | `""` | Language name (required). | | `structure` | `bool` | `true` | Extract structural items (functions, classes, etc.). Default: true. | | `imports` | `bool` | `true` | Extract import statements. Default: true. | | `exports` | `bool` | `true` | Extract export statements. Default: true. | | `comments` | `bool` | `false` | Extract comments. Default: false. | | `docstrings` | `bool` | `false` | Extract docstrings. Default: false. | | `symbols` | `bool` | `false` | Extract symbol definitions. Default: false. | | `diagnostics` | `bool` | `false` | Include parse diagnostics. Default: false. | | `chunk_max_size` | `u64?` | `null` | Maximum chunk size in bytes. `null` disables chunking. `Some(0)` is rejected by `ProcessConfig.validate` with `Error.InvalidRange`. A zero-sized chunk limit previously produced an empty chunk list and silently discarded the whole source; use `null` to mean “do not chunk”. | | `data_extraction` | `bool` | `false` | Extract hierarchical key/value data tree from data-format files. Default: false. When `true`, `ProcessResult.data` is populated with a `DataNode` tree for supported languages: JSON, YAML, TOML, `.properties`, HCL/HOCON, INI, editorconfig, KDL, CUE, CSV, PSV, PO, nginx config, Caddy config, XML, and DTD. For languages outside this set the field is left as `null`. | | `max_source_bytes` | `u64?` | `null` | Reject source longer than this many bytes instead of parsing it. Default: `null` (unbounded). Tree-sitter allocates and walks proportionally to input size, so an unbounded parse of attacker-supplied input is a denial-of-service vector. The default stays unbounded for backward compatibility; services handling untrusted input should opt in, e.g. with `RECOMMENDED_MAX_SOURCE_BYTES`. Exceeding the limit fails the call with `Error.InvalidRange` — the source is never silently truncated. | | `parse_timeout_ms` | `u64?` | `null` | Wall-clock budget for the parse step, in milliseconds. Default: `null` (no timeout). Enforced through tree-sitter’s parse progress callback, which the parser invokes periodically; cancellation is therefore granular to that callback interval rather than exact. A parse that exceeds the budget fails with `Error.ParseTimeout`. | *** #### ProcessResult [Section titled “ProcessResult”](#processresult) Complete analysis result from processing a source file. Contains metrics, structural analysis, imports/exports, comments, docstrings, symbols, diagnostics, and optionally chunked code segments. Fields are populated based on the `ProcessConfig` flags. | Field | Type | Default | Description | | ------------- | ------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `\[\]const u8` | — | The language name used to parse the source file. | | `metrics` | `FileMetrics` | — | File-level metrics (line counts, byte size, error count). | | `structure` | `\[\]const StructureItem` | `[]` | Top-level structural items (functions, classes, etc.). | | `imports` | `\[\]const ImportInfo` | `[]` | Import statements extracted from the source. | | `exports` | `\[\]const ExportInfo` | `[]` | Export statements extracted from the source. | | `comments` | `\[\]const CommentInfo` | `[]` | Comments extracted from the source. | | `docstrings` | `\[\]const DocstringInfo` | `[]` | Docstrings extracted from the source. | | `symbols` | `\[\]const SymbolInfo` | `[]` | Symbol definitions (variables, types, functions) extracted from the source. | | `diagnostics` | `\[\]const Diagnostic` | `[]` | Parse diagnostics (syntax errors, missing nodes) from tree-sitter. | | `chunks` | `\[\]const CodeChunk` | `[]` | Syntax-aware code chunks produced when chunking is enabled. | | `data` | `DataNode?` | `null` | Hierarchical data tree extracted when `config.data_extraction` is `true`. Populated for supported data-format languages (JSON, YAML, TOML, properties, HCL, INI, XML, CSV, and more). `null` when `data_extraction` is `false` (the default) or when the language is not a recognised data format. See `DataNode` for the shape of the returned tree. | *** #### Span [Section titled “Span”](#span) Byte and line/column range in source code. Represents both byte offsets (for slicing) and human-readable line/column positions (for display and diagnostics). | Field | Type | Default | Description | | -------------- | ----- | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `start_byte` | `u64` | — | Inclusive start byte offset in the source. | | `end_byte` | `u64` | — | Exclusive end byte offset in the source. | | `start_line` | `u64` | — | Zero-indexed line number of the span’s start. | | `start_column` | `u64` | — | Zero-indexed column of the span’s start, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | | `end_line` | `u64` | — | Zero-indexed line number of the span’s end. | | `end_column` | `u64` | — | Zero-indexed column of the span’s end, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | *** #### StructureItem [Section titled “StructureItem”](#structureitem) A structural item (function, class, struct, etc.) in source code. | Field | Type | Default | Description | | ------------- | ------------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `kind` | `StructureKind` | `StructureKind.function` | The kind of structural item. | | `name` | `\[\]const u8?` | `null` | The declared name of the item, if present. | | `visibility` | `\[\]const u8?` | `null` | Visibility modifier (e.g., `"pub"`, `"public"`, `"private"`). | | `span` | `Span` | — | Source span covering the entire item declaration. | | `children` | `\[\]const StructureItem` | `[]` | Nested structural items (e.g., methods within a class). | | `decorators` | `\[\]const \[\]const u8` | `[]` | Decorator or attribute names applied to the item. **Reserved: not yet populated.** Always empty, for every language. Recognising a decorator requires per-language grammar knowledge (a Python `decorated_definition` wrapper, Java/C# annotations, Rust attributes each have a different shape), which no extractor here implements yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | | `doc_comment` | `\[\]const u8?` | `null` | Documentation comment attached to the item, if any. The text of the comment (or run of comments) immediately preceding the item, with no blank line in between, when that comment is classified as a doc comment. Multiple adjacent single-line doc comments (Rust `///`) are joined with `\n` in source order. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`). `null` for every other language, and for a preceding comment that is not in doc-comment form (a plain `#` comment in Python, Ruby, or Elixir) — Python’s docstring convention is captured separately, as `DocstringInfo`, not through this field. | | `signature` | `\[\]const u8?` | `null` | Full signature text of the item (e.g., function parameters and return type). The item’s own source text from its start up to the start of its body (see `StructureItem.body_span`), trimmed of trailing whitespace — for example `fn add(a: i32, b: i32) -> i32` for a Rust function whose body is `{ a + b }`. `null` only when that text is empty, which does not happen for any item `StructureKind` currently reports. Populated for every language and kind this library extracts structure for, since it is derived from `body_span`’s boundary rather than per-language syntax. | | `body_span` | `Span?` | `null` | Source span covering only the body of the item, if distinct from the declaration. | *** #### SymbolInfo [Section titled “SymbolInfo”](#symbolinfo) A symbol (variable, function, type, etc.) extracted from source code. | Field | Type | Default | Description | | ----------------- | --------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `\[\]const u8` | — | The name of the symbol. | | `kind` | `SymbolKind` | `SymbolKind.variable` | The kind of symbol (variable, function, class, etc.). | | `span` | `Span` | — | Source span covering the symbol definition. | | `type_annotation` | `\[\]const u8?` | `null` | Explicit type annotation, if present in the source. | | `doc` | `\[\]const u8?` | `null` | Documentation comment immediately preceding this symbol, resolved by the same walk `StructureItem.doc_comment` uses (see `doc_comment_at`) — never hard-coded `null`. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`) — the languages whose comment classification recognizes a doc-kind comment. `null` for every other language (e.g. Python, Go, Ruby, which have no doc-kind comment classification), and also `null` when a symbol in a supported language simply has no doc comment immediately above it. | *** #### Tree [Section titled “Tree”](#tree) A parsed syntax tree. Cheap to clone (refcount bump). ##### Methods [Section titled “Methods”](#methods-4) ###### root\_node() [Section titled “root\_node()”](#root_node) Return the root `Node` of this tree. **Signature:** ```zig pub fn root_node(self: *const Tree) Node ``` **Example:** ```zig const result = instance.root_node(); ``` **Returns:** `Node` ###### walk() [Section titled “walk()”](#walk-1) Return a `TreeCursor` positioned at the root. **Signature:** ```zig pub fn walk(self: *const Tree) TreeCursor ``` **Example:** ```zig const result = instance.walk(); ``` **Returns:** `TreeCursor` *** #### TreeCursor [Section titled “TreeCursor”](#treecursor) A cursor for traversing a `Tree`. ##### Methods [Section titled “Methods”](#methods-5) ###### node() [Section titled “node()”](#node-1) Return the `Node` at the cursor’s current position. **Signature:** ```zig pub fn node(self: *const TreeCursor) Node ``` **Example:** ```zig const result = instance.node(); ``` **Returns:** `Node` ###### goto\_first\_child() [Section titled “goto\_first\_child()”](#goto_first_child) Move the cursor to the first child of the current node. Returns `true` if a child existed. **Signature:** ```zig pub fn goto_first_child(self: *const TreeCursor) bool ``` **Example:** ```zig const result = instance.goto_first_child(); ``` **Returns:** `bool` ###### goto\_parent() [Section titled “goto\_parent()”](#goto_parent) Move the cursor to the parent of the current node. Returns `true` if a parent existed. **Signature:** ```zig pub fn goto_parent(self: *const TreeCursor) bool ``` **Example:** ```zig const result = instance.goto_parent(); ``` **Returns:** `bool` ###### goto\_next\_sibling() [Section titled “goto\_next\_sibling()”](#goto_next_sibling) Move the cursor to the next sibling of the current node. Returns `true` if a sibling existed. **Signature:** ```zig pub fn goto_next_sibling(self: *const TreeCursor) bool ``` **Example:** ```zig const result = instance.goto_next_sibling(); ``` **Returns:** `bool` ###### field\_name() [Section titled “field\_name()”](#field_name) Return the field name for the current node, if any. **Signature:** ```zig pub fn field_name(self: *const TreeCursor) ?[]u8 ``` **Example:** ```zig const result = instance.field_name(); ``` **Returns:** `?[]u8` *** ### Enums [Section titled “Enums”](#enums) #### DataNodeKind [Section titled “DataNodeKind”](#datanodekind) The kind of a data node extracted from a data-format file. Classifies each node in the hierarchical `DataNode` tree returned when `data_extraction` is enabled on `ProcessConfig`. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract) Unit variants serialize as a bare string (`"KeyValue"`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | -------------------------------------------------------------------------------------------------------------------- | | `key_value` | A key/value pair or mapping (json/toml/properties/yaml/hcl/cue/kdl pair, or a wrapper “object”/“mapping” container). | | `element` | An XML element with a tag name in `key` and attributes in `attributes`. | | `sequence` | A positional sequence item (JSON array element, YAML block sequence item, CSV/PSV row or cell). | *** #### StructureKind [Section titled “StructureKind”](#structurekind) The kind of structural item found in source code. Categorizes top-level and nested declarations such as functions, classes, structs, enums, traits, and more. Use `Other` for language-specific constructs that do not fit a standard category. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-1) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | -------------------------------------------------------------------------------------------------- | | `function` | A free-standing or associated function. | | `method` | A method defined inside a class, struct, trait, or impl block. | | `class` | A class definition. | | `struct` | A struct definition. | | `interface` | An interface or protocol definition. | | `enum` | An enum definition. | | `module` | A module or package declaration. | | `trait` | A trait definition. | | `impl` | An impl block (Rust) or similar implementation block. | | `namespace` | A namespace declaration. | | `other` | A language-specific construct that does not fit any standard category. — Fields: `0`: `[]const u8` | *** #### CommentKind [Section titled “CommentKind”](#commentkind) The kind of a comment found in source code. Distinguishes between single-line comments, block (multi-line) comments, and documentation comments. | Value | Description | | ------- | --------------------------------------------------------------------- | | `line` | A single-line comment (e.g., `// ...` or `# ...`). | | `block` | A block or multi-line comment using slash-star delimiters. | | `doc` | A documentation comment such as `/// ...` or slash-double-star block. | *** #### DocstringFormat [Section titled “DocstringFormat”](#docstringformat) The format of a docstring extracted from source code. Identifies the docstring convention used, which varies by language (e.g., Python triple-quoted strings, JSDoc, Rustdoc `///` comments). ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-2) Unit variants serialize as a bare string (`"JSDoc"`); the `Other` variant serializes as a single-keyed object (`{"Other": "rst"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | --------------------- | ------------------------------------------------------------------------------------------------------ | | `python_triple_quote` | Python triple-quoted string docstring (`"""..."""`). | | `js_doc` | JavaScript/TypeScript JSDoc block comment (opens with two stars, closes with star-slash). | | `rustdoc` | Rust `///` or `//!` doc comment. | | `go_doc` | Go doc comment (a comment block immediately preceding a declaration). | | `java_doc` | Java Javadoc block comment (opens with two stars, closes with star-slash). | | `other` | A language-specific docstring format not covered by the standard variants. — Fields: `0`: `[]const u8` | *** #### ExportKind [Section titled “ExportKind”](#exportkind) The kind of an export statement found in source code. Covers named exports, default exports, and re-exports from other modules. | Value | Description | | ----------- | -------------------------------------------------------------------- | | `named` | A named export (e.g., `export { foo }`). | | `default` | A default export (e.g., `export default foo`). | | `re_export` | A re-export from another module (e.g., `export { foo } from 'bar'`). | *** #### SymbolKind [Section titled “SymbolKind”](#symbolkind) The kind of a symbol definition found in source code. Categorizes symbol definitions such as variables, constants, functions, classes, types, interfaces, enums, and modules. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-3) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Value | Description | | ----------- | ------------------------------------------------------------------------------- | | `variable` | A variable binding. | | `constant` | A constant (immutable binding). | | `function` | A function definition. | | `class` | A class definition. | | `type` | A type alias or typedef. | | `interface` | An interface definition. | | `enum` | An enum definition. | | `module` | A module declaration. | | `other` | A symbol kind not covered by the standard variants. — Fields: `0`: `[]const u8` | *** #### DiagnosticSeverity [Section titled “DiagnosticSeverity”](#diagnosticseverity) Severity level of a diagnostic produced during parsing. Used to classify parse errors, warnings, and informational messages found in the syntax tree. | Value | Description | | --------- | --------------------------------------------------------------- | | `error` | A parse error (e.g., an `ERROR` or `MISSING` node in the tree). | | `warning` | A warning-level diagnostic. | | `info` | An informational diagnostic. | *** ### Errors [Section titled “Errors”](#errors) #### Error [Section titled “Error”](#error) Errors that can occur when using the tree-sitter language pack. Covers language lookup failures, parse errors, query errors, and I/O issues. Feature-gated variants are included when `config`, `download`, or related features are enabled. ##### Matching on `Error` [Section titled “Matching on Error”](#matching-on-error) The set of variants is not stable: new failure modes are added in minor releases, and `Io`, `Json`, and `Toml` exist only under certain feature combinations, so the variant set a downstream crate sees depends on which features it enables. Downstream `match`es must therefore carry a `_` arm; `#[non_exhaustive]` makes the compiler enforce that instead of letting a feature change silently break a build. ##### C ABI error codes [Section titled “C ABI error codes”](#c-abi-error-codes) Each variant alef can see carries an explicit `alef(error_code = N)` allocation that becomes a member of the generated `AlefFfiErrorCode` C enum. These numbers are a public ABI contract: **an allocated number is never reused after its variant is removed**, and a variant’s number never changes, because C callers compare against the value, not the name. New variants take the next free number. 0-4 are reserved by alef, so allocation starts at 100. An unannotated variant is emitted as the unknown code rather than as itself, which silently flattens the taxonomy — annotate every new variant. | Variant | Description | | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language_not_found` | The requested language name (or alias) was not found in the registry. | | `dynamic_load` | A dynamic shared library could not be loaded at runtime. | | `null_language_pointer` | The tree-sitter language function returned a null pointer for the given language name. | | `parser_setup` | The language could not be applied to the parser (e.g., ABI version mismatch). | | `lock_poisoned` | An internal `RwLock` or `Mutex` was poisoned by a previous panic. | | `config` | A configuration file or value was invalid or could not be applied. | | `parse_failed` | The tree-sitter parser returned no tree for the given source input. | | `parse_timeout` | The parse was cancelled because it exceeded its configured wall-clock budget. Raised only when a budget is configured — see `ProcessConfig.parse_timeout_ms`, which defaults to `null`. | | `query_error` | A tree-sitter query could not be compiled or executed. | | `invalid_range` | A byte range was invalid (e.g., end before start, or out of bounds). | | `download` | A parser download from GitHub releases failed. | | `checksum_mismatch` | The downloaded file’s SHA-256 digest did not match the manifest’s expected value. | | `cache_lock` | The cross-process download cache lock file could not be acquired or created. | *** # CLI Reference ## CLI Reference [Section titled “CLI Reference”](#cli-reference) ## `ts-pack` [Section titled “ts-pack”](#ts-pack) Tree-sitter language pack CLI ### `ts-pack cache-dir` [Section titled “ts-pack cache-dir”](#ts-pack-cache-dir) Print the effective cache directory ### `ts-pack clean` [Section titled “ts-pack clean”](#ts-pack-clean) Remove all cached parser libraries ### Options [Section titled “Options”](#options) | Name | Flags | Type | Default | Description | | ------- | --------- | ------ | ------- | ------------------------ | | `force` | `--force` | `bool` | | Skip confirmation prompt | ### `ts-pack completions` [Section titled “ts-pack completions”](#ts-pack-completions) Generate shell completions ### Arguments [Section titled “Arguments”](#arguments) | Name | Flags | Type | Default | Description | | ------- | ----- | ---------------------- | ------- | --------------------------------- | | `shell` | | `clap_complete::Shell` | | Shell to generate completions for | ### `ts-pack download` [Section titled “ts-pack download”](#ts-pack-download) Download parser libraries ### Arguments [Section titled “Arguments”](#arguments-1) | Name | Flags | Type | Default | Description | | ----------- | ----- | ------------- | ------- | -------------------------------------------------- | | `languages` | | `Vec` | | Languages to download (omit for all or use config) | ### Options [Section titled “Options”](#options-1) | Name | Flags | Type | Default | Description | | -------- | ---------- | ------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | | `all` | `--all` | `bool` | | Download all available languages | | `groups` | `--groups` | `Vec` | | Download language groups (comma-separated). The manifest currently defines exactly one group, `all`; enumerate the real names with `manifest_groups()`. | | `fresh` | `--fresh` | `bool` | | Clean cache before downloading (fresh download) | ### `ts-pack info` [Section titled “ts-pack info”](#ts-pack-info) Show details about a language ### Arguments [Section titled “Arguments”](#arguments-2) | Name | Flags | Type | Default | Description | | ---------- | ----- | -------- | ------- | ------------- | | `language` | | `String` | | Language name | ### `ts-pack init` [Section titled “ts-pack init”](#ts-pack-init) Create a language-pack.toml config file ### Options [Section titled “Options”](#options-2) | Name | Flags | Type | Default | Description | | ----------- | ------------- | ---------------- | ------- | ---------------------------------------------------------------------------------- | | `cache_dir` | `--cache-dir` | `Option` | | Base directory for the parser cache (a versioned subdirectory is created under it) | | `languages` | `--languages` | `Vec` | | Languages to include (comma-separated) | ### `ts-pack list` [Section titled “ts-pack list”](#ts-pack-list) List available languages ### Options [Section titled “Options”](#options-3) | Name | Flags | Type | Default | Description | | ------------ | -------------- | ---------------- | ------- | --------------------------------------- | | `downloaded` | `--downloaded` | `bool` | | Show only downloaded/cached languages | | `manifest` | `--manifest` | `bool` | | Show all languages from remote manifest | | `filter` | `--filter` | `Option` | | Filter languages by substring | ### `ts-pack mcp` [Section titled “ts-pack mcp”](#ts-pack-mcp) Start the MCP (Model Context Protocol) server ### `ts-pack parse` [Section titled “ts-pack parse”](#ts-pack-parse) Parse a file and output the syntax tree ### Arguments [Section titled “Arguments”](#arguments-3) | Name | Flags | Type | Default | Description | | ------ | ----- | -------- | ------- | --------------------------------- | | `file` | | `String` | | File to parse (use “-” for stdin) | ### Options [Section titled “Options”](#options-4) | Name | Flags | Type | Default | Description | | ---------- | ------------ | ---------------- | ------- | -------------------------------------------------- | | `language` | `--language` | `Option` | | Language (auto-detected from extension if omitted) | | `format` | `--format` | `ParseFormat` | `sexp` | Output format | ### `ts-pack process` [Section titled “ts-pack process”](#ts-pack-process) Run code intelligence pipeline ### Arguments [Section titled “Arguments”](#arguments-4) | Name | Flags | Type | Default | Description | | ------ | ----- | -------- | ------- | ----------------------------------- | | `file` | | `String` | | File to process (use “-” for stdin) | ### Options [Section titled “Options”](#options-5) | Name | Flags | Type | Default | Description | | ------------- | --------------- | ---------------- | ------- | -------------------------------------------------- | | `language` | `--language` | `Option` | | Language (auto-detected from extension if omitted) | | `all` | `--all` | `bool` | | Enable all analysis features | | `structure` | `--structure` | `bool` | | Extract structure (functions, classes) | | `imports` | `--imports` | `bool` | | Extract imports | | `exports` | `--exports` | `bool` | | Extract exports | | `comments` | `--comments` | `bool` | | Extract comments | | `symbols` | `--symbols` | `bool` | | Extract symbols | | `docstrings` | `--docstrings` | `bool` | | Extract docstrings | | `diagnostics` | `--diagnostics` | `bool` | | Include diagnostics | | `chunk_size` | `--chunk-size` | `Option` | | Maximum chunk size in bytes | # Configuration Reference ## Configuration Reference [Section titled “Configuration Reference”](#configuration-reference) This page documents all configuration types and their defaults across all languages. ### DataAttribute [Section titled “DataAttribute”](#dataattribute) An XML-style attribute attached to an `Element` node. Populated only for `DataNodeKind.Element`; always empty for `KeyValue` and `Sequence` nodes. | Field | Type | Default | Description | | ------- | ------ | ------- | --------------------------------------------------------------- | | `name` | `str` | — | Attribute name (e.g. `"class"`, `"href"`). | | `value` | `str` | — | Attribute value as a raw string (quotes stripped). | | `span` | `Span` | — | Source span covering the entire `name="value"` attribute token. | *** ### DataNode [Section titled “DataNode”](#datanode) A node in the hierarchical data tree produced by data-format extraction. When `ProcessConfig.data_extraction` is `True`, `ProcessResult.data` is populated with a root `DataNode` whose `children` mirror the structure of the parsed file. The `kind` field determines which other fields are meaningful: | `kind` | `key` | `value` | `attributes` | `children` | | ---------- | ------------------------- | ------------ | ------------ | -------------- | | `KeyValue` | key / mapping key / index | leaf value | empty | nested map | | `Element` | XML tag name | text content | XML attrs | child elements | | `Sequence` | positional index (`"0"`) | leaf value | empty | sub-items | | Field | Type | Default | Description | | ------------ | ----------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------- | | `kind` | `DataNodeKind` | `DataNodeKind.KEY_VALUE` | Whether this node is a key/value pair, XML element, or sequence item. | | `key` | `str \| None` | `None` | Key, attribute name, tag name, or positional index (`"0"`, `"1"`, …). `None` at the document root. | | `value` | `str \| None` | `None` | Leaf scalar value, if any. `None` for containers (objects, arrays, XML elements with child elements). | | `attributes` | `list\[DataAttribute\]` | `[]` | Attributes on element-shape nodes (XML `STag` attributes). Empty for all other kinds. | | `children` | `list\[DataNode\]` | `[]` | Children for nested containers and XML element bodies. | | `span` | `Span` | — | Source span covering this node in the original source file. | *** ### Span [Section titled “Span”](#span) Byte and line/column range in source code. Represents both byte offsets (for slicing) and human-readable line/column positions (for display and diagnostics). | Field | Type | Default | Description | | -------------- | ----- | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `start_byte` | `int` | — | Inclusive start byte offset in the source. | | `end_byte` | `int` | — | Exclusive end byte offset in the source. | | `start_line` | `int` | — | Zero-indexed line number of the span’s start. | | `start_column` | `int` | — | Zero-indexed column of the span’s start, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | | `end_line` | `int` | — | Zero-indexed line number of the span’s end. | | `end_column` | `int` | — | Zero-indexed column of the span’s end, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | *** ### ProcessResult [Section titled “ProcessResult”](#processresult) Complete analysis result from processing a source file. Contains metrics, structural analysis, imports/exports, comments, docstrings, symbols, diagnostics, and optionally chunked code segments. Fields are populated based on the `ProcessConfig` flags. | Field | Type | Default | Description | | ------------- | ----------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `str` | — | The language name used to parse the source file. | | `metrics` | `FileMetrics` | — | File-level metrics (line counts, byte size, error count). | | `structure` | `list\[StructureItem\]` | `[]` | Top-level structural items (functions, classes, etc.). | | `imports` | `list\[ImportInfo\]` | `[]` | Import statements extracted from the source. | | `exports` | `list\[ExportInfo\]` | `[]` | Export statements extracted from the source. | | `comments` | `list\[CommentInfo\]` | `[]` | Comments extracted from the source. | | `docstrings` | `list\[DocstringInfo\]` | `[]` | Docstrings extracted from the source. | | `symbols` | `list\[SymbolInfo\]` | `[]` | Symbol definitions (variables, types, functions) extracted from the source. | | `diagnostics` | `list\[Diagnostic\]` | `[]` | Parse diagnostics (syntax errors, missing nodes) from tree-sitter. | | `chunks` | `list\[CodeChunk\]` | `[]` | Syntax-aware code chunks produced when chunking is enabled. | | `data` | `DataNode \| None` | `None` | Hierarchical data tree extracted when `config.data_extraction` is `True`. Populated for supported data-format languages (JSON, YAML, TOML, properties, HCL, INI, XML, CSV, and more). `None` when `data_extraction` is `False` (the default) or when the language is not a recognised data format. See `DataNode` for the shape of the returned tree. | *** ### FileMetrics [Section titled “FileMetrics”](#filemetrics) Aggregate metrics for a source file. | Field | Type | Default | Description | | --------------- | ----- | ------- | -------------------------------------------------------------- | | `total_lines` | `int` | — | Total number of lines (including blank and comment lines). | | `code_lines` | `int` | — | Number of lines containing non-blank, non-comment source code. | | `comment_lines` | `int` | — | Number of lines that are entirely comments. | | `blank_lines` | `int` | — | Number of blank (whitespace-only) lines. | | `total_bytes` | `int` | — | Total byte length of the source file. | | `node_count` | `int` | — | Total number of nodes in the syntax tree. | | `error_count` | `int` | — | Number of error nodes in the syntax tree (parse errors). | | `max_depth` | `int` | — | Maximum nesting depth reached in the syntax tree. | *** ### StructureItem [Section titled “StructureItem”](#structureitem) A structural item (function, class, struct, etc.) in source code. | Field | Type | Default | Description | | ------------- | ----------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `kind` | `StructureKind` | `StructureKind.FUNCTION` | The kind of structural item. | | `name` | `str \| None` | `None` | The declared name of the item, if present. | | `visibility` | `str \| None` | `None` | Visibility modifier (e.g., `"pub"`, `"public"`, `"private"`). | | `span` | `Span` | — | Source span covering the entire item declaration. | | `children` | `list\[StructureItem\]` | `[]` | Nested structural items (e.g., methods within a class). | | `decorators` | `list\[str\]` | `[]` | Decorator or attribute names applied to the item. **Reserved: not yet populated.** Always empty, for every language. Recognising a decorator requires per-language grammar knowledge (a Python `decorated_definition` wrapper, Java/C# annotations, Rust attributes each have a different shape), which no extractor here implements yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | | `doc_comment` | `str \| None` | `None` | Documentation comment attached to the item, if any. The text of the comment (or run of comments) immediately preceding the item, with no blank line in between, when that comment is classified as a doc comment. Multiple adjacent single-line doc comments (Rust `///`) are joined with `\n` in source order. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`). `None` for every other language, and for a preceding comment that is not in doc-comment form (a plain `#` comment in Python, Ruby, or Elixir) — Python’s docstring convention is captured separately, as `DocstringInfo`, not through this field. | | `signature` | `str \| None` | `None` | Full signature text of the item (e.g., function parameters and return type). The item’s own source text from its start up to the start of its body (see `StructureItem.body_span`), trimmed of trailing whitespace — for example `fn add(a: i32, b: i32) -> i32` for a Rust function whose body is `{ a + b }`. `None` only when that text is empty, which does not happen for any item `StructureKind` currently reports. Populated for every language and kind this library extracts structure for, since it is derived from `body_span`’s boundary rather than per-language syntax. | | `body_span` | `Span \| None` | `None` | Source span covering only the body of the item, if distinct from the declaration. | *** ### CommentInfo [Section titled “CommentInfo”](#commentinfo) A comment extracted from source code. | Field | Type | Default | Description | | ----------------- | ------------- | ------------------ | ----------------------------------------------------------------- | | `text` | `str` | — | The raw text content of the comment. | | `kind` | `CommentKind` | `CommentKind.LINE` | The kind of comment (line, block, or doc). | | `span` | `Span` | — | Source span covering the comment. | | `associated_node` | `str \| None` | `None` | Name of the syntax node this comment is directly associated with. | *** ### DocstringInfo [Section titled “DocstringInfo”](#docstringinfo) A docstring extracted from source code. | Field | Type | Default | Description | | ----------------- | -------------------- | ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | `str` | — | The raw text of the docstring. | | `format` | `DocstringFormat` | `DocstringFormat.PYTHON_TRIPLE_QUOTE` | The docstring format (Python, JSDoc, Rustdoc, etc.). | | `span` | `Span` | — | Source span covering the docstring. | | `associated_item` | `str \| None` | `None` | Name of the item this docstring documents. | | `parsed_sections` | `list\[DocSection\]` | `[]` | Parsed sections of the docstring (Args, Returns, Raises, etc.). **Reserved: not yet populated.** Always empty, for every `DocstringFormat`. Parsing a docstring body into sections requires implementing each convention’s own layout (Google/NumPy/reST style for Python, `@param`/`@returns` for JSDoc/Javadoc, and so on), which no extractor here does yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | *** ### DocSection [Section titled “DocSection”](#docsection) A section within a docstring (e.g., Args, Returns, Raises). | Field | Type | Default | Description | | ------------- | ------------- | ------- | ------------------------------------------------------- | | `kind` | `str` | — | Section kind (e.g., `"args"`, `"returns"`, `"raises"`). | | `name` | `str \| None` | `None` | Parameter or return value name, if applicable. | | `description` | `str` | — | Description text for this section. | *** ### ImportInfo [Section titled “ImportInfo”](#importinfo) An import statement extracted from source code. | Field | Type | Default | Description | | ------------- | ------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `source` | `str` | — | The module or path being imported from. | | `items` | `list\[str\]` | `[]` | Specific names imported from the source module. For `import a, b` / `from m import a, b`, every entry’s base name (never the alias). For a JavaScript/TypeScript named-imports clause (`import { a, b as c } from 'm'`), every specifier’s original name. Populated for Python and JavaScript/TypeScript only. Always empty for every other language this library recognises import statements for — Rust, Go, Java, Kotlin, and Elixir (`import`/`alias`/`require`/`use`) — and for a JS/TS namespace import (`import * as ns`) or default import (`import x from 'm'`), neither of which names individual items. | | `alias` | `str \| None` | `None` | Alias assigned to the import (e.g., `import numpy as np`). Populated for Python’s single-name form (`import numpy as np`, `from m import a as b`) and JavaScript/TypeScript’s namespace form (`import * as ns from 'm'`) or a named-imports clause naming exactly one specifier (`import { a as b } from 'm'`). `None` for Rust, Go, Java, Kotlin, and Elixir (which has its own `as:` alias option on `alias` directives, not yet extracted here) — and for a Python statement that aliases several names at once (`import os, sys as s`), where there is no single alias to report for the statement as a whole, so only `items` is populated for it. | | `is_wildcard` | `bool` | — | Whether this is a wildcard import (e.g., `import *` or `use foo.*`). Detected from the syntax tree — a dedicated wildcard node (`wildcard_import` in Python, `use_wildcard` in Rust) or a bare `*` token outside of string-literal content — not by searching the import’s source text for a `*` character, so a glob in an import path string (`import a from './glob*.js'`) is not mistaken for one. | | `span` | `Span` | — | Source span covering the import statement. | *** ### ExportInfo [Section titled “ExportInfo”](#exportinfo) An export statement extracted from source code. | Field | Type | Default | Description | | ------ | ------------ | ------------------ | -------------------------------------------------- | | `name` | `str` | — | The exported name. | | `kind` | `ExportKind` | `ExportKind.NAMED` | The kind of export (named, default, or re-export). | | `span` | `Span` | — | Source span covering the export statement. | *** ### SymbolInfo [Section titled “SymbolInfo”](#symbolinfo) A symbol (variable, function, type, etc.) extracted from source code. | Field | Type | Default | Description | | ----------------- | ------------- | --------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `str` | — | The name of the symbol. | | `kind` | `SymbolKind` | `SymbolKind.VARIABLE` | The kind of symbol (variable, function, class, etc.). | | `span` | `Span` | — | Source span covering the symbol definition. | | `type_annotation` | `str \| None` | `None` | Explicit type annotation, if present in the source. | | `doc` | `str \| None` | `None` | Documentation comment immediately preceding this symbol, resolved by the same walk `StructureItem.doc_comment` uses (see `doc_comment_at`) — never hard-coded `None`. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`) — the languages whose comment classification recognizes a doc-kind comment. `None` for every other language (e.g. Python, Go, Ruby, which have no doc-kind comment classification), and also `None` when a symbol in a supported language simply has no doc comment immediately above it. | *** ### Diagnostic [Section titled “Diagnostic”](#diagnostic) A diagnostic (syntax error, missing node, etc.) from parsing. | Field | Type | Default | Description | | ---------- | -------------------- | -------------------------- | ---------------------------------------------- | | `message` | `str` | — | Human-readable description of the diagnostic. | | `severity` | `DiagnosticSeverity` | `DiagnosticSeverity.ERROR` | Severity of the diagnostic. | | `span` | `Span` | — | Source span where the diagnostic was detected. | *** ### CodeChunk [Section titled “CodeChunk”](#codechunk) A chunk of source code with rich metadata. | Field | Type | Default | Description | | ------------ | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `content` | `str` | — | The raw source text of this chunk. | | `start_byte` | `int` | — | Inclusive start byte offset of this chunk in the original source. | | `end_byte` | `int` | — | Exclusive end byte offset of this chunk in the original source. | | `start_line` | `int` | — | Zero-indexed start line of this chunk. | | `end_line` | `int` | — | Zero-indexed row of the last byte actually included in this chunk (inclusive — the same row a `Span.end_line` would report for a node ending on that byte). Computed the same way regardless of whether the source has a trailing newline: it is always the row of `end_byte - 1`, never a phantom row past the file’s real content. | | `metadata` | `ChunkContext` | — | Contextual metadata about this chunk. | *** ### ChunkContext [Section titled “ChunkContext”](#chunkcontext) Metadata for a single chunk of source code. | Field | Type | Default | Description | | ----------------- | ----------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `str` | — | Language name used to parse this chunk. | | `chunk_index` | `int` | — | Zero-indexed position of this chunk within the file’s chunk list. | | `total_chunks` | `int` | — | Total number of chunks the file was split into. | | `node_types` | `list\[str\]` | `[]` | Tree-sitter node kinds that appear at the top level of this chunk. | | `context_path` | `list\[str\]` | `[]` | Hierarchical path of enclosing structural items (e.g., `["MyClass", "my_method"]`). | | `symbols_defined` | `list\[str\]` | `[]` | Names of symbols defined within this chunk. | | `comments` | `list\[CommentInfo\]` | `[]` | Comments contained within this chunk. | | `docstrings` | `list\[DocstringInfo\]` | `[]` | Docstrings contained within this chunk. Populated only for Python — the same language for which `ProcessResult.docstrings` is populated, and by the same classifier. Always empty for every other language. | | `has_error_nodes` | `bool` | — | Whether this chunk contains any tree-sitter error nodes. | *** ### PackConfig [Section titled “PackConfig”](#packconfig) Configuration for the tree-sitter language pack. Controls cache directory and which languages to pre-download. Can be loaded from a TOML file, constructed programmatically, or passed as a dict/object from language bindings. | Field | Type | Default | Description | | ----------- | --------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cache_dir` | `str \| None` | `None` | Override the BASE directory the parser cache lives under. This is a base, not the final library path: the crate appends `tree-sitter-language-pack/v{version}/libs` to it, exactly as it does to the platform default. So `cache_dir = "/tmp/my-parsers"` resolves to `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`. The suffix is not cosmetic. It keeps the whole cache tree — manifest, bundles and lock file included — inside a directory this library owns and versions. Earlier releases used this path verbatim, which put those files in the configured directory’s PARENT and let a cache built by one crate version be reused by another. Default base: the platform cache dir, e.g. `~/.cache` on Linux. | | `languages` | `list\[str\] \| None` | `[]` | Languages to pre-download on init. Each entry is a language name (e.g. `"python"`, `"rust"`). | | `groups` | `list\[str\] \| None` | `[]` | Language groups to pre-download. Group names come from the remote manifest, so the valid set is not fixed by this library; the published manifest currently defines only `"all"`. Call `manifest_groups` to enumerate them. An unknown name makes `init` fail. | *** ### ProcessConfig [Section titled “ProcessConfig”](#processconfig) Configuration for the `process()` function. Controls which analysis features are enabled and whether chunking is performed. | Field | Type | Default | Description | | ------------------ | ------------- | ------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `str` | `""` | Language name (required). | | `structure` | `bool` | `True` | Extract structural items (functions, classes, etc.). Default: true. | | `imports` | `bool` | `True` | Extract import statements. Default: true. | | `exports` | `bool` | `True` | Extract export statements. Default: true. | | `comments` | `bool` | `False` | Extract comments. Default: false. | | `docstrings` | `bool` | `False` | Extract docstrings. Default: false. | | `symbols` | `bool` | `False` | Extract symbol definitions. Default: false. | | `diagnostics` | `bool` | `False` | Include parse diagnostics. Default: false. | | `chunk_max_size` | `int \| None` | `None` | Maximum chunk size in bytes. `None` disables chunking. `Some(0)` is rejected by `ProcessConfig.validate` with `Error.InvalidRange`. A zero-sized chunk limit previously produced an empty chunk list and silently discarded the whole source; use `None` to mean “do not chunk”. | | `data_extraction` | `bool` | `False` | Extract hierarchical key/value data tree from data-format files. Default: false. When `True`, `ProcessResult.data` is populated with a `DataNode` tree for supported languages: JSON, YAML, TOML, `.properties`, HCL/HOCON, INI, editorconfig, KDL, CUE, CSV, PSV, PO, nginx config, Caddy config, XML, and DTD. For languages outside this set the field is left as `None`. | | `max_source_bytes` | `int \| None` | `None` | Reject source longer than this many bytes instead of parsing it. Default: `None` (unbounded). Tree-sitter allocates and walks proportionally to input size, so an unbounded parse of attacker-supplied input is a denial-of-service vector. The default stays unbounded for backward compatibility; services handling untrusted input should opt in, e.g. with `RECOMMENDED_MAX_SOURCE_BYTES`. Exceeding the limit fails the call with `Error.InvalidRange` — the source is never silently truncated. | | `parse_timeout_ms` | `int \| None` | `None` | Wall-clock budget for the parse step, in milliseconds. Default: `None` (no timeout). Enforced through tree-sitter’s parse progress callback, which the parser invokes periodically; cancellation is therefore granular to that callback interval rather than exact. A parse that exceeds the budget fails with `Error.ParseTimeout`. | *** ### Enums [Section titled “Enums”](#enums) #### CommentKind [Section titled “CommentKind”](#commentkind) The kind of a comment found in source code. Distinguishes between single-line comments, block (multi-line) comments, and documentation comments. | Variant | Description | | ------- | --------------------------------------------------------------------- | | `Line` | A single-line comment (e.g., `// ...` or `# ...`). | | `Block` | A block or multi-line comment using slash-star delimiters. | | `Doc` | A documentation comment such as `/// ...` or slash-double-star block. | *** #### DataNodeKind [Section titled “DataNodeKind”](#datanodekind) The kind of a data node extracted from a data-format file. Classifies each node in the hierarchical `DataNode` tree returned when `data_extraction` is enabled on `ProcessConfig`. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract) Unit variants serialize as a bare string (`"KeyValue"`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Variant | Description | | ---------- | -------------------------------------------------------------------------------------------------------------------- | | `KeyValue` | A key/value pair or mapping (json/toml/properties/yaml/hcl/cue/kdl pair, or a wrapper “object”/“mapping” container). | | `Element` | An XML element with a tag name in `key` and attributes in `attributes`. | | `Sequence` | A positional sequence item (JSON array element, YAML block sequence item, CSV/PSV row or cell). | *** #### DiagnosticSeverity [Section titled “DiagnosticSeverity”](#diagnosticseverity) Severity level of a diagnostic produced during parsing. Used to classify parse errors, warnings, and informational messages found in the syntax tree. | Variant | Description | | --------- | --------------------------------------------------------------- | | `Error` | A parse error (e.g., an `ERROR` or `MISSING` node in the tree). | | `Warning` | A warning-level diagnostic. | | `Info` | An informational diagnostic. | *** #### DocstringFormat [Section titled “DocstringFormat”](#docstringformat) The format of a docstring extracted from source code. Identifies the docstring convention used, which varies by language (e.g., Python triple-quoted strings, JSDoc, Rustdoc `///` comments). ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-1) Unit variants serialize as a bare string (`"JSDoc"`); the `Other` variant serializes as a single-keyed object (`{"Other": "rst"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Variant | Description | | ------------------- | --------------------------------------------------------------------------------------------------- | | `PythonTripleQuote` | Python triple-quoted string docstring (`"""..."""`). | | `JSDoc` | JavaScript/TypeScript JSDoc block comment (opens with two stars, closes with star-slash). | | `Rustdoc` | Rust `///` or `//!` doc comment. | | `GoDoc` | Go doc comment (a comment block immediately preceding a declaration). | | `JavaDoc` | Java Javadoc block comment (opens with two stars, closes with star-slash). | | `Other` | A language-specific docstring format not covered by the standard variants. — Fields: `_0`: `String` | *** #### ExportKind [Section titled “ExportKind”](#exportkind) The kind of an export statement found in source code. Covers named exports, default exports, and re-exports from other modules. | Variant | Description | | ---------- | -------------------------------------------------------------------- | | `Named` | A named export (e.g., `export { foo }`). | | `Default` | A default export (e.g., `export default foo`). | | `ReExport` | A re-export from another module (e.g., `export { foo } from 'bar'`). | *** #### StructureKind [Section titled “StructureKind”](#structurekind) The kind of structural item found in source code. Categorizes top-level and nested declarations such as functions, classes, structs, enums, traits, and more. Use `Other` for language-specific constructs that do not fit a standard category. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-2) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Variant | Description | | ----------- | ----------------------------------------------------------------------------------------------- | | `Function` | A free-standing or associated function. | | `Method` | A method defined inside a class, struct, trait, or impl block. | | `Class` | A class definition. | | `Struct` | A struct definition. | | `Interface` | An interface or protocol definition. | | `Enum` | An enum definition. | | `Module` | A module or package declaration. | | `Trait` | A trait definition. | | `Impl` | An impl block (Rust) or similar implementation block. | | `Namespace` | A namespace declaration. | | `Other` | A language-specific construct that does not fit any standard category. — Fields: `_0`: `String` | *** #### SymbolKind [Section titled “SymbolKind”](#symbolkind) The kind of a symbol definition found in source code. Categorizes symbol definitions such as variables, constants, functions, classes, types, interfaces, enums, and modules. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-3) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Variant | Description | | ----------- | ---------------------------------------------------------------------------- | | `Variable` | A variable binding. | | `Constant` | A constant (immutable binding). | | `Function` | A function definition. | | `Class` | A class definition. | | `Type` | A type alias or typedef. | | `Interface` | An interface definition. | | `Enum` | An enum definition. | | `Module` | A module declaration. | | `Other` | A symbol kind not covered by the standard variants. — Fields: `_0`: `String` | *** # Error Reference ## Error Reference [Section titled “Error Reference”](#error-reference) All error types thrown by the library across all languages. ### Error [Section titled “Error”](#error) Errors that can occur when using the tree-sitter language pack. Covers language lookup failures, parse errors, query errors, and I/O issues. Feature-gated variants are included when `config`, `download`, or related features are enabled. #### Matching on `Error` [Section titled “Matching on Error”](#matching-on-error) The set of variants is not stable: new failure modes are added in minor releases, and `Io`, `Json`, and `Toml` exist only under certain feature combinations, so the variant set a downstream crate sees depends on which features it enables. Downstream `match`es must therefore carry a `_` arm; `#[non_exhaustive]` makes the compiler enforce that instead of letting a feature change silently break a build. #### C ABI error codes [Section titled “C ABI error codes”](#c-abi-error-codes) Each variant alef can see carries an explicit `alef(error_code = N)` allocation that becomes a member of the generated `AlefFfiErrorCode` C enum. These numbers are a public ABI contract: **an allocated number is never reused after its variant is removed**, and a variant’s number never changes, because C callers compare against the value, not the name. New variants take the next free number. 0-4 are reserved by alef, so allocation starts at 100. An unannotated variant is emitted as the unknown code rather than as itself, which silently flattens the taxonomy — annotate every new variant. | Variant | Message | Description | | --------------------- | ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `LanguageNotFound` | Language ‘{0}’ not found | The requested language name (or alias) was not found in the registry. | | `DynamicLoad` | Dynamic library load error: {0} | A dynamic shared library could not be loaded at runtime. | | `NullLanguagePointer` | Language function returned null pointer for ‘{0}’ | The tree-sitter language function returned a null pointer for the given language name. | | `ParserSetup` | Failed to set parser language: {0} | The language could not be applied to the parser (e.g., ABI version mismatch). | | `LockPoisoned` | Registry lock poisoned: {0} | An internal `RwLock` or `Mutex` was poisoned by a previous panic. | | `Config` | Configuration error: {0} | A configuration file or value was invalid or could not be applied. | | `ParseFailed` | Parse failed: parsing returned no tree | The tree-sitter parser returned no tree for the given source input. | | `ParseTimeout` | Parse cancelled: exceeded the configured budget of {timeout\_ms} ms | The parse was cancelled because it exceeded its configured wall-clock budget. Raised only when a budget is configured — see `ProcessConfig.parse_timeout_ms`, which defaults to `None`. | | `QueryError` | Query error: {0} | A tree-sitter query could not be compiled or executed. | | `InvalidRange` | Invalid byte range: {0} | A byte range was invalid (e.g., end before start, or out of bounds). | | `Download` | Download error: {0} | A parser download from GitHub releases failed. | | `ChecksumMismatch` | Checksum mismatch for ‘{file}’: expected {expected}, got {actual} | The downloaded file’s SHA-256 digest did not match the manifest’s expected value. | | `CacheLock` | Download cache lock error: {0} | The cross-process download cache lock file could not be acquired or created. | *** # MCP Reference ## MCP Reference [Section titled “MCP Reference”](#mcp-reference) ### Tools [Section titled “Tools”](#tools) | Name | Title | Parameters | Description | | ----------------- | --------------- | ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | | `cache_dir` | Cache Directory | | Return the effective parser cache directory path. | | `clean_cache` | Clean Cache | | Delete all cached parser libraries from the cache directory. | | `detect_language` | Detect Language | `Parameters` | Detect the language for a file path or source content. Returns the detected language name. | | `download` | Download | `Parameters` | Download parser libraries from the remote registry. Pass languages list, groups, or all=true. \
Set fresh=true to clean the cache first. | | `info` | Language Info | `Parameters` | Show whether a language is known, downloaded, and its cache path. | | `list_languages` | List Languages | `Parameters` | List languages. source: ‘available’ (default), ‘downloaded’, or ‘manifest’. Optional substring filter. | | `parse` | Parse | `Parameters` | Parse source code with a tree-sitter grammar. Returns the syntax tree as sexp or JSON. | | `process` | Process | `Parameters` | Run the code-intelligence pipeline on source code. Extracts structure, imports, exports, symbols, and more. | # Types Reference ## Types Reference [Section titled “Types Reference”](#types-reference) All types defined by the library, grouped by category. Types are shown using Rust as the canonical representation. ### Result Types [Section titled “Result Types”](#result-types) #### ProcessResult [Section titled “ProcessResult”](#processresult) Complete analysis result from processing a source file. Contains metrics, structural analysis, imports/exports, comments, docstrings, symbols, diagnostics, and optionally chunked code segments. Fields are populated based on the `ProcessConfig` flags. | Field | Type | Default | Description | | ------------- | -------------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `language` | `String` | — | The language name used to parse the source file. | | `metrics` | `FileMetrics` | — | File-level metrics (line counts, byte size, error count). | | `structure` | `Vec` | `vec![]` | Top-level structural items (functions, classes, etc.). | | `imports` | `Vec` | `vec![]` | Import statements extracted from the source. | | `exports` | `Vec` | `vec![]` | Export statements extracted from the source. | | `comments` | `Vec` | `vec![]` | Comments extracted from the source. | | `docstrings` | `Vec` | `vec![]` | Docstrings extracted from the source. | | `symbols` | `Vec` | `vec![]` | Symbol definitions (variables, types, functions) extracted from the source. | | `diagnostics` | `Vec` | `vec![]` | Parse diagnostics (syntax errors, missing nodes) from tree-sitter. | | `chunks` | `Vec` | `vec![]` | Syntax-aware code chunks produced when chunking is enabled. | | `data` | `Option` | `Default::default()` | Hierarchical data tree extracted when `config.data_extraction` is `true`. Populated for supported data-format languages (JSON, YAML, TOML, properties, HCL, INI, XML, CSV, and more). `None` when `data_extraction` is `false` (the default) or when the language is not a recognised data format. See `DataNode` for the shape of the returned tree. | *** ### Configuration Types [Section titled “Configuration Types”](#configuration-types) See [Configuration Reference](configuration.md) for detailed defaults and language-specific representations. #### DataAttribute [Section titled “DataAttribute”](#dataattribute) An XML-style attribute attached to an `Element` node. Populated only for `DataNodeKind.Element`; always empty for `KeyValue` and `Sequence` nodes. | Field | Type | Default | Description | | ------- | -------- | ------- | --------------------------------------------------------------- | | `name` | `String` | — | Attribute name (e.g. `"class"`, `"href"`). | | `value` | `String` | — | Attribute value as a raw string (quotes stripped). | | `span` | `Span` | — | Source span covering the entire `name="value"` attribute token. | *** #### DataNode [Section titled “DataNode”](#datanode) A node in the hierarchical data tree produced by data-format extraction. When `ProcessConfig.data_extraction` is `True`, `ProcessResult.data` is populated with a root `DataNode` whose `children` mirror the structure of the parsed file. The `kind` field determines which other fields are meaningful: | `kind` | `key` | `value` | `attributes` | `children` | | ---------- | ------------------------- | ------------ | ------------ | -------------- | | `KeyValue` | key / mapping key / index | leaf value | empty | nested map | | `Element` | XML tag name | text content | XML attrs | child elements | | `Sequence` | positional index (`"0"`) | leaf value | empty | sub-items | | Field | Type | Default | Description | | ------------ | -------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------- | | `kind` | `DataNodeKind` | `DataNodeKind::KeyValue` | Whether this node is a key/value pair, XML element, or sequence item. | | `key` | `Option` | `Default::default()` | Key, attribute name, tag name, or positional index (`"0"`, `"1"`, …). `None` at the document root. | | `value` | `Option` | `Default::default()` | Leaf scalar value, if any. `None` for containers (objects, arrays, XML elements with child elements). | | `attributes` | `Vec` | `vec![]` | Attributes on element-shape nodes (XML `STag` attributes). Empty for all other kinds. | | `children` | `Vec` | `vec![]` | Children for nested containers and XML element bodies. | | `span` | `Span` | — | Source span covering this node in the original source file. | *** #### Span [Section titled “Span”](#span) Byte and line/column range in source code. Represents both byte offsets (for slicing) and human-readable line/column positions (for display and diagnostics). | Field | Type | Default | Description | | -------------- | ------- | ------- | --------------------------------------------------------------------------------------------------------------------------------- | | `start_byte` | `usize` | — | Inclusive start byte offset in the source. | | `end_byte` | `usize` | — | Exclusive end byte offset in the source. | | `start_line` | `usize` | — | Zero-indexed line number of the span’s start. | | `start_column` | `usize` | — | Zero-indexed column of the span’s start, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | | `end_line` | `usize` | — | Zero-indexed line number of the span’s end. | | `end_column` | `usize` | — | Zero-indexed column of the span’s end, counted in **bytes** from the start of the line — not characters, not UTF-16 code units. | *** #### FileMetrics [Section titled “FileMetrics”](#filemetrics) Aggregate metrics for a source file. | Field | Type | Default | Description | | --------------- | ------- | ------- | -------------------------------------------------------------- | | `total_lines` | `usize` | — | Total number of lines (including blank and comment lines). | | `code_lines` | `usize` | — | Number of lines containing non-blank, non-comment source code. | | `comment_lines` | `usize` | — | Number of lines that are entirely comments. | | `blank_lines` | `usize` | — | Number of blank (whitespace-only) lines. | | `total_bytes` | `usize` | — | Total byte length of the source file. | | `node_count` | `usize` | — | Total number of nodes in the syntax tree. | | `error_count` | `usize` | — | Number of error nodes in the syntax tree (parse errors). | | `max_depth` | `usize` | — | Maximum nesting depth reached in the syntax tree. | *** #### StructureItem [Section titled “StructureItem”](#structureitem) A structural item (function, class, struct, etc.) in source code. | Field | Type | Default | Description | | ------------- | -------------------- | ------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `kind` | `StructureKind` | `StructureKind::Function` | The kind of structural item. | | `name` | `Option` | `Default::default()` | The declared name of the item, if present. | | `visibility` | `Option` | `Default::default()` | Visibility modifier (e.g., `"pub"`, `"public"`, `"private"`). | | `span` | `Span` | — | Source span covering the entire item declaration. | | `children` | `Vec` | `vec![]` | Nested structural items (e.g., methods within a class). | | `decorators` | `Vec` | `vec![]` | Decorator or attribute names applied to the item. **Reserved: not yet populated.** Always empty, for every language. Recognising a decorator requires per-language grammar knowledge (a Python `decorated_definition` wrapper, Java/C# annotations, Rust attributes each have a different shape), which no extractor here implements yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | | `doc_comment` | `Option` | `Default::default()` | Documentation comment attached to the item, if any. The text of the comment (or run of comments) immediately preceding the item, with no blank line in between, when that comment is classified as a doc comment. Multiple adjacent single-line doc comments (Rust `///`) are joined with `\n` in source order. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`). `None` for every other language, and for a preceding comment that is not in doc-comment form (a plain `#` comment in Python, Ruby, or Elixir) — Python’s docstring convention is captured separately, as `DocstringInfo`, not through this field. | | `signature` | `Option` | `Default::default()` | Full signature text of the item (e.g., function parameters and return type). The item’s own source text from its start up to the start of its body (see `StructureItem::body_span`), trimmed of trailing whitespace — for example `fn add(a: i32, b: i32) -> i32` for a Rust function whose body is `{ a + b }`. `None` only when that text is empty, which does not happen for any item `StructureKind` currently reports. Populated for every language and kind this library extracts structure for, since it is derived from `body_span`’s boundary rather than per-language syntax. | | `body_span` | `Option` | `Default::default()` | Source span covering only the body of the item, if distinct from the declaration. | *** #### CommentInfo [Section titled “CommentInfo”](#commentinfo) A comment extracted from source code. | Field | Type | Default | Description | | ----------------- | ---------------- | -------------------- | ----------------------------------------------------------------- | | `text` | `String` | — | The raw text content of the comment. | | `kind` | `CommentKind` | `CommentKind::Line` | The kind of comment (line, block, or doc). | | `span` | `Span` | — | Source span covering the comment. | | `associated_node` | `Option` | `Default::default()` | Name of the syntax node this comment is directly associated with. | *** #### DocstringInfo [Section titled “DocstringInfo”](#docstringinfo) A docstring extracted from source code. | Field | Type | Default | Description | | ----------------- | ----------------- | ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `text` | `String` | — | The raw text of the docstring. | | `format` | `DocstringFormat` | `DocstringFormat::PythonTripleQuote` | The docstring format (Python, JSDoc, Rustdoc, etc.). | | `span` | `Span` | — | Source span covering the docstring. | | `associated_item` | `Option` | `Default::default()` | Name of the item this docstring documents. | | `parsed_sections` | `Vec` | `vec![]` | Parsed sections of the docstring (Args, Returns, Raises, etc.). **Reserved: not yet populated.** Always empty, for every `DocstringFormat`. Parsing a docstring body into sections requires implementing each convention’s own layout (Google/NumPy/reST style for Python, `@param`/`@returns` for JSDoc/Javadoc, and so on), which no extractor here does yet. The field is kept rather than removed so a consumer’s deserializer does not need updating once it is. | *** #### DocSection [Section titled “DocSection”](#docsection) A section within a docstring (e.g., Args, Returns, Raises). | Field | Type | Default | Description | | ------------- | ---------------- | -------------------- | ------------------------------------------------------- | | `kind` | `String` | — | Section kind (e.g., `"args"`, `"returns"`, `"raises"`). | | `name` | `Option` | `Default::default()` | Parameter or return value name, if applicable. | | `description` | `String` | — | Description text for this section. | *** #### ImportInfo [Section titled “ImportInfo”](#importinfo) An import statement extracted from source code. | Field | Type | Default | Description | | ------------- | ---------------- | -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `source` | `String` | — | The module or path being imported from. | | `items` | `Vec` | `vec![]` | Specific names imported from the source module. For `import a, b` / `from m import a, b`, every entry’s base name (never the alias). For a JavaScript/TypeScript named-imports clause (`import { a, b as c } from 'm'`), every specifier’s original name. Populated for Python and JavaScript/TypeScript only. Always empty for every other language this library recognises import statements for — Rust, Go, Java, Kotlin, and Elixir (`import`/`alias`/`require`/`use`) — and for a JS/TS namespace import (`import * as ns`) or default import (`import x from 'm'`), neither of which names individual items. | | `alias` | `Option` | `Default::default()` | Alias assigned to the import (e.g., `import numpy as np`). Populated for Python’s single-name form (`import numpy as np`, `from m import a as b`) and JavaScript/TypeScript’s namespace form (`import * as ns from 'm'`) or a named-imports clause naming exactly one specifier (`import { a as b } from 'm'`). `None` for Rust, Go, Java, Kotlin, and Elixir (which has its own `as:` alias option on `alias` directives, not yet extracted here) — and for a Python statement that aliases several names at once (`import os, sys as s`), where there is no single alias to report for the statement as a whole, so only `items` is populated for it. | | `is_wildcard` | `bool` | — | Whether this is a wildcard import (e.g., `import *` or `use foo::*`). Detected from the syntax tree — a dedicated wildcard node (`wildcard_import` in Python, `use_wildcard` in Rust) or a bare `*` token outside of string-literal content — not by searching the import’s source text for a `*` character, so a glob in an import path string (`import a from './glob*.js'`) is not mistaken for one. | | `span` | `Span` | — | Source span covering the import statement. | *** #### ExportInfo [Section titled “ExportInfo”](#exportinfo) An export statement extracted from source code. | Field | Type | Default | Description | | ------ | ------------ | ------------------- | -------------------------------------------------- | | `name` | `String` | — | The exported name. | | `kind` | `ExportKind` | `ExportKind::Named` | The kind of export (named, default, or re-export). | | `span` | `Span` | — | Source span covering the export statement. | *** #### SymbolInfo [Section titled “SymbolInfo”](#symbolinfo) A symbol (variable, function, type, etc.) extracted from source code. | Field | Type | Default | Description | | ----------------- | ---------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `name` | `String` | — | The name of the symbol. | | `kind` | `SymbolKind` | `SymbolKind::Variable` | The kind of symbol (variable, function, class, etc.). | | `span` | `Span` | — | Source span covering the symbol definition. | | `type_annotation` | `Option` | `Default::default()` | Explicit type annotation, if present in the source. | | `doc` | `Option` | `Default::default()` | Documentation comment immediately preceding this symbol, resolved by the same walk `StructureItem::doc_comment` uses (see `doc_comment_at`) — never hard-coded `None`. Populated for Rust (`///`/`//!`), Java (`/** */`), and JavaScript/ TypeScript (`/** */`) — the languages whose comment classification recognizes a doc-kind comment. `None` for every other language (e.g. Python, Go, Ruby, which have no doc-kind comment classification), and also `None` when a symbol in a supported language simply has no doc comment immediately above it. | *** #### Diagnostic [Section titled “Diagnostic”](#diagnostic) A diagnostic (syntax error, missing node, etc.) from parsing. | Field | Type | Default | Description | | ---------- | -------------------- | --------------------------- | ---------------------------------------------- | | `message` | `String` | — | Human-readable description of the diagnostic. | | `severity` | `DiagnosticSeverity` | `DiagnosticSeverity::Error` | Severity of the diagnostic. | | `span` | `Span` | — | Source span where the diagnostic was detected. | *** #### CodeChunk [Section titled “CodeChunk”](#codechunk) A chunk of source code with rich metadata. | Field | Type | Default | Description | | ------------ | -------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `content` | `String` | — | The raw source text of this chunk. | | `start_byte` | `usize` | — | Inclusive start byte offset of this chunk in the original source. | | `end_byte` | `usize` | — | Exclusive end byte offset of this chunk in the original source. | | `start_line` | `usize` | — | Zero-indexed start line of this chunk. | | `end_line` | `usize` | — | Zero-indexed row of the last byte actually included in this chunk (inclusive — the same row a `Span::end_line` would report for a node ending on that byte). Computed the same way regardless of whether the source has a trailing newline: it is always the row of `end_byte - 1`, never a phantom row past the file’s real content. | | `metadata` | `ChunkContext` | — | Contextual metadata about this chunk. | *** #### ChunkContext [Section titled “ChunkContext”](#chunkcontext) Metadata for a single chunk of source code. | Field | Type | Default | Description | | ----------------- | -------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `language` | `String` | — | Language name used to parse this chunk. | | `chunk_index` | `usize` | — | Zero-indexed position of this chunk within the file’s chunk list. | | `total_chunks` | `usize` | — | Total number of chunks the file was split into. | | `node_types` | `Vec` | `vec![]` | Tree-sitter node kinds that appear at the top level of this chunk. | | `context_path` | `Vec` | `vec![]` | Hierarchical path of enclosing structural items (e.g., `["MyClass", "my_method"]`). | | `symbols_defined` | `Vec` | `vec![]` | Names of symbols defined within this chunk. | | `comments` | `Vec` | `vec![]` | Comments contained within this chunk. | | `docstrings` | `Vec` | `vec![]` | Docstrings contained within this chunk. Populated only for Python — the same language for which `ProcessResult::docstrings` is populated, and by the same classifier. Always empty for every other language. | | `has_error_nodes` | `bool` | — | Whether this chunk contains any tree-sitter error nodes. | *** #### PackConfig [Section titled “PackConfig”](#packconfig) Configuration for the tree-sitter language pack. Controls cache directory and which languages to pre-download. Can be loaded from a TOML file, constructed programmatically, or passed as a dict/object from language bindings. | Field | Type | Default | Description | | ----------- | ----------------- | -------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cache_dir` | `Option` | `Default::default()` | Override the BASE directory the parser cache lives under. This is a base, not the final library path: the crate appends `tree-sitter-language-pack/v{version}/libs` to it, exactly as it does to the platform default. So `cache_dir = "/tmp/my-parsers"` resolves to `/tmp/my-parsers/tree-sitter-language-pack/v{version}/libs/`. The suffix is not cosmetic. It keeps the whole cache tree — manifest, bundles and lock file included — inside a directory this library owns and versions. Earlier releases used this path verbatim, which put those files in the configured directory’s PARENT and let a cache built by one crate version be reused by another. Default base: the platform cache dir, e.g. `~/.cache` on Linux. | | `languages` | `Vec` | `vec![]` | Languages to pre-download on init. Each entry is a language name (e.g. `"python"`, `"rust"`). | | `groups` | `Vec` | `vec![]` | Language groups to pre-download. Group names come from the remote manifest, so the valid set is not fixed by this library; the published manifest currently defines only `"all"`. Call `manifest_groups` to enumerate them. An unknown name makes `init` fail. | *** #### Parser [Section titled “Parser”](#parser) A tree-sitter parser configured for one language at a time. *Opaque type — fields are not directly accessible.* *** #### ProcessConfig [Section titled “ProcessConfig”](#processconfig) Configuration for the `process()` function. Controls which analysis features are enabled and whether chunking is performed. | Field | Type | Default | Description | | ------------------ | --------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `language` | `String` | `""` | Language name (required). | | `structure` | `bool` | `true` | Extract structural items (functions, classes, etc.). Default: true. | | `imports` | `bool` | `true` | Extract import statements. Default: true. | | `exports` | `bool` | `true` | Extract export statements. Default: true. | | `comments` | `bool` | `false` | Extract comments. Default: false. | | `docstrings` | `bool` | `false` | Extract docstrings. Default: false. | | `symbols` | `bool` | `false` | Extract symbol definitions. Default: false. | | `diagnostics` | `bool` | `false` | Include parse diagnostics. Default: false. | | `chunk_max_size` | `Option` | `None` | Maximum chunk size in bytes. `None` disables chunking. `Some(0)` is rejected by `ProcessConfig::validate` with `Error::InvalidRange`. A zero-sized chunk limit previously produced an empty chunk list and silently discarded the whole source; use `None` to mean “do not chunk”. | | `data_extraction` | `bool` | `false` | Extract hierarchical key/value data tree from data-format files. Default: false. When `true`, `ProcessResult::data` is populated with a `DataNode` tree for supported languages: JSON, YAML, TOML, `.properties`, HCL/HOCON, INI, editorconfig, KDL, CUE, CSV, PSV, PO, nginx config, Caddy config, XML, and DTD. For languages outside this set the field is left as `None`. | | `max_source_bytes` | `Option` | `None` | Reject source longer than this many bytes instead of parsing it. Default: `None` (unbounded). Tree-sitter allocates and walks proportionally to input size, so an unbounded parse of attacker-supplied input is a denial-of-service vector. The default stays unbounded for backward compatibility; services handling untrusted input should opt in, e.g. with `RECOMMENDED_MAX_SOURCE_BYTES`. Exceeding the limit fails the call with `Error::InvalidRange` — the source is never silently truncated. | | `parse_timeout_ms` | `Option` | `None` | Wall-clock budget for the parse step, in milliseconds. Default: `None` (no timeout). Enforced through tree-sitter’s parse progress callback, which the parser invokes periodically; cancellation is therefore granular to that callback interval rather than exact. A parse that exceeds the budget fails with `Error::ParseTimeout`. | *** #### LanguageRegistry [Section titled “LanguageRegistry”](#languageregistry) Thread-safe registry of tree-sitter language parsers. Manages both statically compiled and dynamically loaded language grammars. Use `LanguageRegistry.new()` for the default registry, or access the global instance via the module-level convenience functions (`get_language`, `available_languages`, etc.). *Opaque type — fields are not directly accessible.* *** ### Structured Data Types [Section titled “Structured Data Types”](#structured-data-types) #### Node [Section titled “Node”](#node) A single syntax node within a `Tree`. Nodes hold a strong reference to their parent tree so they remain valid regardless of how the tree is moved or stored at the FFI boundary. *Opaque type — fields are not directly accessible.* *** ### Other Types [Section titled “Other Types”](#other-types) #### Point [Section titled “Point”](#point) A source position — row + column, zero-indexed. | Field | Type | Default | Description | | -------- | ------- | ------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `row` | `usize` | — | Zero-indexed row number. | | `column` | `usize` | — | Zero-indexed column, counted in **bytes** from the start of the row. This is `tree_sitter::Point::column` verbatim, and tree-sitter defines it as a byte offset — not characters, and not UTF-16 code units. Measured on a row of the form `x = ''` where `` is a single 4-byte character (an emoji), the string node reports columns `4..10`, identical to its byte range; the character columns would be `4..7` and the UTF-16 columns `4..8`. Anything that builds LSP positions (UTF-16) or editor caret columns (characters) from this field is silently wrong on every row containing a non-ASCII byte, and must re-measure the row against the source text instead. Earlier releases documented this field as UTF-16 code units; that was never what the value contained. | *** #### ByteRange [Section titled “ByteRange”](#byterange) A byte range — start (inclusive) to end (exclusive). | Field | Type | Default | Description | | ------- | ------- | ------- | ---------------------------- | | `start` | `usize` | — | Inclusive start byte offset. | | `end` | `usize` | — | Exclusive end byte offset. | *** #### Tree [Section titled “Tree”](#tree) A parsed syntax tree. Cheap to clone (refcount bump). *Opaque type — fields are not directly accessible.* *** #### TreeCursor [Section titled “TreeCursor”](#treecursor) A cursor for traversing a `Tree`. *Opaque type — fields are not directly accessible.* *** #### DownloadManager [Section titled “DownloadManager”](#downloadmanager) Manages downloading and caching of pre-built parser shared libraries. *Opaque type — fields are not directly accessible.* *** #### Language [Section titled “Language”](#language) *Opaque type — fields are not directly accessible.* *** ### Enums [Section titled “Enums”](#enums) #### CommentKind [Section titled “CommentKind”](#commentkind) The kind of a comment found in source code. Distinguishes between single-line comments, block (multi-line) comments, and documentation comments. | Variant | Description | | ------- | --------------------------------------------------------------------- | | `Line` | A single-line comment (e.g., `// ...` or `# ...`). | | `Block` | A block or multi-line comment using slash-star delimiters. | | `Doc` | A documentation comment such as `/// ...` or slash-double-star block. | *** #### DataNodeKind [Section titled “DataNodeKind”](#datanodekind) The kind of a data node extracted from a data-format file. Classifies each node in the hierarchical `DataNode` tree returned when `data_extraction` is enabled on `ProcessConfig`. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract) Unit variants serialize as a bare string (`"KeyValue"`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Variant | Description | | ---------- | -------------------------------------------------------------------------------------------------------------------- | | `KeyValue` | A key/value pair or mapping (json/toml/properties/yaml/hcl/cue/kdl pair, or a wrapper “object”/“mapping” container). | | `Element` | An XML element with a tag name in `key` and attributes in `attributes`. | | `Sequence` | A positional sequence item (JSON array element, YAML block sequence item, CSV/PSV row or cell). | *** #### DiagnosticSeverity [Section titled “DiagnosticSeverity”](#diagnosticseverity) Severity level of a diagnostic produced during parsing. Used to classify parse errors, warnings, and informational messages found in the syntax tree. | Variant | Description | | --------- | --------------------------------------------------------------- | | `Error` | A parse error (e.g., an `ERROR` or `MISSING` node in the tree). | | `Warning` | A warning-level diagnostic. | | `Info` | An informational diagnostic. | *** #### DocstringFormat [Section titled “DocstringFormat”](#docstringformat) The format of a docstring extracted from source code. Identifies the docstring convention used, which varies by language (e.g., Python triple-quoted strings, JSDoc, Rustdoc `///` comments). ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-1) Unit variants serialize as a bare string (`"JSDoc"`); the `Other` variant serializes as a single-keyed object (`{"Other": "rst"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Variant | Description | | ------------------- | --------------------------------------------------------------------------------------------------- | | `PythonTripleQuote` | Python triple-quoted string docstring (`"""..."""`). | | `JSDoc` | JavaScript/TypeScript JSDoc block comment (opens with two stars, closes with star-slash). | | `Rustdoc` | Rust `///` or `//!` doc comment. | | `GoDoc` | Go doc comment (a comment block immediately preceding a declaration). | | `JavaDoc` | Java Javadoc block comment (opens with two stars, closes with star-slash). | | `Other` | A language-specific docstring format not covered by the standard variants. — Fields: `_0`: `String` | *** #### ExportKind [Section titled “ExportKind”](#exportkind) The kind of an export statement found in source code. Covers named exports, default exports, and re-exports from other modules. | Variant | Description | | ---------- | -------------------------------------------------------------------- | | `Named` | A named export (e.g., `export { foo }`). | | `Default` | A default export (e.g., `export default foo`). | | `ReExport` | A re-export from another module (e.g., `export { foo } from 'bar'`). | *** #### StructureKind [Section titled “StructureKind”](#structurekind) The kind of structural item found in source code. Categorizes top-level and nested declarations such as functions, classes, structs, enums, traits, and more. Use `Other` for language-specific constructs that do not fit a standard category. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-2) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]` or rename variants — every language binding has a hand-written deserializer matching this exact shape, and any change breaks all bindings’ `process()` tests simultaneously. Covered by `tests/wire_format.rs`. | Variant | Description | | ----------- | ----------------------------------------------------------------------------------------------- | | `Function` | A free-standing or associated function. | | `Method` | A method defined inside a class, struct, trait, or impl block. | | `Class` | A class definition. | | `Struct` | A struct definition. | | `Interface` | An interface or protocol definition. | | `Enum` | An enum definition. | | `Module` | A module or package declaration. | | `Trait` | A trait definition. | | `Impl` | An impl block (Rust) or similar implementation block. | | `Namespace` | A namespace declaration. | | `Other` | A language-specific construct that does not fit any standard category. — Fields: `_0`: `String` | *** #### SymbolKind [Section titled “SymbolKind”](#symbolkind) The kind of a symbol definition found in source code. Categorizes symbol definitions such as variables, constants, functions, classes, types, interfaces, enums, and modules. ##### Wire format (public JSON contract) [Section titled “Wire format (public JSON contract)”](#wire-format-public-json-contract-3) Unit variants serialize as a bare string (`"Function"`); the `Other` variant serializes as a single-keyed object (`{"Other": "macro"}`). DO NOT add `#[serde(tag = "...")]`. Covered by `tests/wire_format.rs`. | Variant | Description | | ----------- | ---------------------------------------------------------------------------- | | `Variable` | A variable binding. | | `Constant` | A constant (immutable binding). | | `Function` | A function definition. | | `Class` | A class definition. | | `Type` | A type alias or typedef. | | `Interface` | An interface definition. | | `Enum` | An enum definition. | | `Module` | A module declaration. | | `Other` | A symbol kind not covered by the standard variants. — Fields: `_0`: `String` | ***