tree-sitter-kotlin

repository·main·Indexed 41 days ago

https://github.com/fwcd/tree-sitter-kotlin

A Tree-sitter grammar for the Kotlin language (v0.4.0) designed for high-fidelity parsing, syntax highlighting, and code analysis. Includes bindings for Rust and Node.js, as well as a cross-validation toolset to ensure AST structural accuracy against the official JetBrains Kotlin compiler PSI reference parser.

Tokens
2.7K
Snippets
13
Records
15
Agent score
52%

What's inside tree-sitter-kotlin

  1. How JetBrains Cross-Validation works

    main

    The project uses cross-validation to compare the tree-sitter-kotlin parse trees against the official JetBrains Kotlin compiler's PSI reference parser. This ensures the grammar accurately reproduces the official AST structure.

    The process involves:

    1. Vendoring: Fetching JetBrains PSI test fixtures (.kt source + .txt expected PSI tree) at a pinned commit.
    2. Corpus Generation: Parsing these files with tree-sitter; files that parse cleanly (and aren't in excluded.txt) become corpus tests.
    3. Structural Comparison: Comparing tree-sitter output against JetBrains' expected PSI tree using 110+ node type mappings.
    4. Issue Tracking: Files that produce incorrect ASTs are tracked in tools/cross-validation/excluded.txt and categorized in tools/cross-validation/TODO.md.
  2. Update JetBrains test fixtures

    main

    To update the grammar's reference to a newer version of the JetBrains test fixtures, follow these steps. Note that the commit hash is stored in tools/cross-validation/.fixtures-version for reproducibility; you must commit this file when updating.

    # Update to a specific commit
    npm run vendor-fixtures -- <new-commit-hash>
    
    # Regenerate corpus tests
    npm run vendor-jetbrains
    
    # Run tests
    npm test
    
    # Check for new matches or regressions
    npm run cross-validate
  3. Compile to WebAssembly and use the Playground

    main

    To use the grammar in a browser-based environment, you must first compile it to WebAssembly using Emscripten.

    Requirements:

    • Emscripten installed (e.g., via brew install emscripten).
    • Node.js 18+
    • tree-sitter-cli

    Steps:

    1. Compile to WASM: npm run build-wasm
    2. Launch interactive playground: npm run playground
    # Compile WASM
    npm run build-wasm
    
    # Launch playground
    npm run playground
  4. Use tree-sitter-kotlin in Rust projects

    main

    To use the Kotlin grammar in a Rust project, add tree-sitter and tree-sitter-kotlin to your Cargo.toml dependencies. You can then use the tree_sitter_kotlin::language() function to provide the grammar to a tree_sitter::Parser instance via set_language().

    tree-sitter = "0.23"
    tree-sitter-kotlin = "0.3.9"
  5. Generate corpus tests with vendor-jetbrains.js

    main

    The vendor-jetbrains.js tool generates tree-sitter corpus tests from the vendored JetBrains fixtures located in cross-validation/fixtures/.

    Process:

    1. Iterates through .kt files in the fixtures directory.
    2. Skips *_ERR.kt files and files listed in cross-validation/excluded.txt.
    3. Parses files using the tree-sitter parse CLI.
    4. Filters out files that produce ERROR nodes or MISSING keyword tokens.
    5. Converts zero-length named nodes into (MISSING _alpha_identifier) syntax.
    6. Outputs one corpus test file per fixture to test/corpus/jetbrains/<Name>.txt.

    Requirements:

    • tree-sitter CLI (must be installed via npm install)
    # Uses default fixtures path (tools/cross-validation/fixtures/)
    npm run vendor-jetbrains
    
    # Pass custom fixtures path as argument
    npm run vendor-jetbrains -- /path/to/fixtures
  6. Quick Start for tree-sitter-kotlin tools

    main

    All tools in this repository are written in Node.js and work on Windows, macOS, and Linux without requiring Python or bash. Use the following sequence to set up the environment, fetch JetBrains fixtures, generate tests, and run validation suites.

    1. Install dependencies: Includes vitest for unit tests.
    2. Fetch JetBrains fixtures: A one-time setup to download Kotlin PSI test fixtures.
    3. Generate corpus tests: Converts fetched fixtures into tree-sitter corpus tests.
    4. Run tests: Executes all tree-sitter tests (including the JetBrains corpus).
    5. Run cross-validation: Compares tree-sitter parse trees against JetBrains PSI reference trees.
    6. Run cross-validation unit tests: Executes unit tests for the cross-validation tool itself.
    # Install dependencies
    npm install
    
    # Fetch JetBrains fixtures (one-time setup)
    npm run vendor-fixtures
    
    # Generate corpus tests from fixtures
    npm run vendor-jetbrains
    
    # Run all tree-sitter tests (includes JetBrains corpus)
    npm test
    
    # Run structural cross-validation
    npm run cross-validate
    
    # Run cross-validation unit tests
    npm run cross-validate:test
  7. Perform structural cross-validation

    main

    The cross-validation tool in the cross-validation/ directory compares tree-sitter-kotlin parse trees against JetBrains PSI reference trees to ensure grammatical accuracy.

    How it works:

    1. Parses JetBrains .kt fixtures using tree-sitter parse.
    2. Parses corresponding .txt PSI fixtures (indented tree format).
    3. Normalizes both trees using over 110 node type mappings, noise skipping, and wrapper collapsing.
    4. Performs a structural comparison and records mismatches.
    5. Generates a Markdown report (report.md) containing the analysis.

    Usage:

    • Full validation: Run the complete suite.
    • Debug single fixture: Run validation for a specific fixture name.
    • Unit tests: Run tests for the cross-validation tool itself using vitest.
    # Full validation
    npm run cross-validate
    
    # Debug a single fixture
    npm run cross-validate:debug -- BabySteps
    
    # Run unit tests (vitest)
    npm run cross-validate:test
  8. Run tests for the Kotlin grammar

    main

    You can run the unit tests using the test script. For manual verification, you can also run the tree-sitter CLI directly on Kotlin source files to inspect the parse tree and statistics.

    # Run unit tests
    npm run test
    
    # Manually parse a project file
    ./node_modules/.bin/tree-sitter parse "/path/to/some/project/**/*.kt" --quiet --stat
  9. Fetch JetBrains Kotlin PSI fixtures with vendor-fixtures.js

    main

    The vendor-fixtures.js tool fetches JetBrains Kotlin PSI test fixtures using a sparse checkout at a specific commit hash. Fixtures are not checked into git; they are fetched on demand to ensure reproducibility via the .fixtures-version file.

    Workflow:

    1. Reads the pinned commit from cross-validation/.fixtures-version.
    2. Sparse-clones compiler/testData/psi/ from the JetBrains/kotlin repository.
    3. Copies .kt and .txt files into cross-validation/fixtures/.
    4. Updates .fixtures-version if a new commit hash is provided.

    Requirements:

    • Git (for sparse checkout)
    • Node.js
    # Fetch at pinned commit (from .fixtures-version)
    npm run vendor-fixtures
    
    # Fetch at a specific commit (updates .fixtures-version)
    npm run vendor-fixtures -- <commit-hash>
  10. Parse Kotlin code with tree-sitter-kotlin in Rust

    main

    To parse Kotlin source code, initialize a tree_sitter::Parser, set its language using tree_sitter_kotlin::language(), and then call parse().

    let code = r"#
      data class Point(
        val x: Int,
        val y: Int
      )
    "#;
    let mut parser = Parser::new();
    parser.set_language(&tree_sitter_kotlin::language()).expect("Error loading Kotlin grammar");
    let parsed = parser.parse(code, None);