treesitter-types-php 0.2.0

Pre-generated strongly-typed AST types for PHP (tree-sitter-php)
Documentation

treesitter-types

CI crates.io docs.rs license

Generate fully-typed Rust structs and enums from any tree-sitter grammar's node-types.json.

Instead of stringly-typed access like node.kind() == "function_declaration", get compile-time checked types with proper field access, Option<T> for optional fields, Vec<T> for repeated fields, and enums for alternations.

Usage

Via build.rs (recommended)

Add to your Cargo.toml:

[dependencies]
treesitter-types = "0.1"

[build-dependencies]
treesitter-types = "0.1"

Create a build.rs:

fn main() {
    treesitter_types::codegen::emit_to_out_dir("path/to/node-types.json").unwrap();
}

Include the generated code in lib.rs:

include!(concat!(env!("OUT_DIR"), "/treesitter_types_generated.rs"));

Via proc-macro

[dependencies]
treesitter-types = "0.1"
treesitter-types-macros = "0.1"
treesitter_types_macros::generate_types!("path/to/node-types.json");

Example

Given tree-sitter-go's node-types.json, the generated types let you write:

use treesitter_types_go::*;

let mut parser = tree_sitter::Parser::new();
parser.set_language(&tree_sitter_go::LANGUAGE.into()).unwrap();
let tree = parser.parse(src, None).unwrap();
let source_file = SourceFile::from_node(tree.root_node(), src).unwrap();

for child in &source_file.children {
    match child {
        SourceFileChildren::FunctionDeclaration(func) => {
            println!("fn {}", func.name.text());
        }
        SourceFileChildren::PackageClause(pkg) => {
            println!("package {}", pkg.children.text());
        }
        _ => {}
    }
}

What gets generated

Grammar construct Rust type
Named node with fields struct with typed fields
Named terminal node struct with LeafNode::text()
Supertype node (_expression) enum with variant per subtype
Field with multiple types Alternation enum
Optional field Option<T>
Repeated field Vec<T>
All named nodes AnyNode top-level enum

Runtime traits

Every generated type implements:

  • FromNode<'tree> - construct from a tree_sitter::Node
  • Spanned - access source location (span(), start(), end())
  • LeafNode<'tree> (terminal nodes only) - access source text via text()

Pre-generated language crates

Ready-to-use typed AST crates for 25 languages — no codegen step needed:

Crate Grammar
treesitter-types-bash tree-sitter-bash
treesitter-types-c tree-sitter-c
treesitter-types-c-sharp tree-sitter-c-sharp
treesitter-types-cpp tree-sitter-cpp
treesitter-types-css tree-sitter-css
treesitter-types-elixir tree-sitter-elixir
treesitter-types-go tree-sitter-go
treesitter-types-haskell tree-sitter-haskell
treesitter-types-html tree-sitter-html
treesitter-types-java tree-sitter-java
treesitter-types-javascript tree-sitter-javascript
treesitter-types-json tree-sitter-json
treesitter-types-lua tree-sitter-lua
treesitter-types-markdown tree-sitter-md
treesitter-types-php tree-sitter-php
treesitter-types-python tree-sitter-python
treesitter-types-regex tree-sitter-regex
treesitter-types-ruby tree-sitter-ruby
treesitter-types-rust tree-sitter-rust
treesitter-types-scala tree-sitter-scala
treesitter-types-swift tree-sitter-swift
treesitter-types-toml tree-sitter-toml-ng
treesitter-types-typescript tree-sitter-typescript
treesitter-types-yaml tree-sitter-yaml
[dependencies]
treesitter-types-python = "0.1"

Each language crate re-exports tree_sitter and its grammar crate (e.g. tree_sitter_python), so no extra dependencies are needed.

Tested against

The codegen is validated against real-world repositories with zero failures on cleanly-parsed files:

Repository Language Files Result
golang/go Go 5,670 100%
rust-lang/rust Rust 11,109 100%
microsoft/TypeScript TypeScript 709 100%
nodejs/node JavaScript 356 100%
spring-projects/spring-framework Java 4,715 100%
python/cpython Python - -
git/git C - -
nlohmann/json C++ - -
ohmyzsh/ohmyzsh Bash - -
rails/rails Ruby - -
dotnet/runtime C# - -
twbs/bootstrap CSS - -
laravel/framework PHP - -
SchemaStore/schemastore JSON - -
apache/spark Scala - -
haskell/cabal Haskell - -

Run the integration tests yourself:

just integration-test-go
just integration-test-python
just integration-test-all    # run all languages

License

Licensed under either of Apache License, Version 2.0 or MIT License at your option.